Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to pass function as child? #71

Open
Siilwyn opened this issue Aug 8, 2018 · 7 comments
Open

How to pass function as child? #71

Siilwyn opened this issue Aug 8, 2018 · 7 comments

Comments

@Siilwyn
Copy link
Contributor

Siilwyn commented Aug 8, 2018

👋 hi, wondering how to pass a function to a component. Trying to use the Query component from react-apollo.

const hyperx = require('hyperx');
const { Query } = require('react-apollo');
const gql = require('graphql-tag');
const { createElement } = require('react');

const hx = hyperx(createElement);

hx`<${Query}
  query=${gql`
    {
      // query here
    }
  `}
>
  ${({ loading, error, data }) => {
    // function content here
  }}
</${Query}>`

Returns:

Failed prop type: Invalid prop `children` of type `array` supplied to `Query`, expected `function`.
    in Query
@Siilwyn
Copy link
Contributor Author

Siilwyn commented Nov 13, 2018

@goto-bus-stop @substack is passing a function as a child possible at all?

@goto-bus-stop
Copy link
Member

I don't think so. it might work if you pass it as the children=${fn} prop instead though

@Siilwyn
Copy link
Contributor Author

Siilwyn commented Nov 13, 2018

@goto-bus-stop ah okay, thank you for you reply!

That's a bummer, I've been looking around for a JSX alternative because I don't like the magic, seems that there is no replacement out there yet.

@Siilwyn
Copy link
Contributor Author

Siilwyn commented Nov 13, 2018

This isn't restricted to apollo btw. I've seen react components accept functions before. Just tested with GatsbyJS too:

import React from 'react';
import { StaticQuery, graphql } from 'gatsby';
import hyperx from 'hyperx';

const hx = hyperx(React.createElement);

export default ({ children }) => hx`
  <${StaticQuery}
    query=${graphql`
      {
        site {
          siteMetadata {
            title
          }
        }
      }
    `}
    render=${() => {}}
  />
`;

Interestingly enough this gives a different error though: Objects are not valid as a React child (found: object with keys {query, render}). If you meant to render a collection of children, use an array instead.. Probably because this is a self closing tag.

@Siilwyn
Copy link
Contributor Author

Siilwyn commented Nov 13, 2018

Funny thing is the above is a pretty bad example, I would say the following using just createElement is even more readable:

import { createElement } from 'react';
import { StaticQuery, graphql } from 'gatsby';

export default ({ children }) => createElement(
  StaticQuery,
  {
    query: graphql`
      {
        site {
          siteMetadata {
            title
          }
        }
      }
    `,
    render: () => {},
  }
);

Though mixing hyperx and the use of createElement could be very confusing to some developers. I'll keep poking. :)

@goto-bus-stop
Copy link
Member

We could probably loosen the type check to allow function children, but I also agree that using createelement is nicer. I'd alias it to something like h and use it for all custom components, then just use hyperx for the native HTML nodes. you could also look into hyperscript (there is a react version of it but I forgot the name) if you haven't already, it's like a fancier createElement function, no template strings

@Siilwyn
Copy link
Contributor Author

Siilwyn commented Nov 14, 2018

Hmm loosening the type check could be desirable because I'm not sure if in all cases createElement is nicer... Thanks for the tip, I know hyperscript but prefer hyperx because it's closer to HTML.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants