skip to Main Content

I was trying to modify and clone child elements of a component I am creating and recently noticed that the type of children I was getting changed depending on how I pass the children.

For example if I pass JSX as a children:

<MyComponent>
  <div>Hello</div>
</MyComponent>

When I check for the children structure within MyComponent I can see that the object is as follow:

{
  '$$typeof': Symbol(react.element),
  type: 'div',
  key: null,
  ref: null,
  props: { children: 'hello' },
  _owner: null,
  _store: {}
}

This can be directly used by React.cloneElement since props.children is present.

If instead I create a functional component like this:

const Hello: React.FC = () => <div>hello</div>;

And try to use it like this:

<MyComponent>
  <Hello/>
</MyComponent>

Then the structure of the children object becomes this:

{
  '$$typeof': Symbol(react.element),
  type: [Function: Hello],
  key: null,
  ref: null,
  props: {},
  _owner: null,
  _store: {}
}

I can no longer use React.cloneElement unless I call children.type() which I could not find much documentation on.

Why is this happening and is this expected? And is calling children.type() the only way to clone the entire tree of child elements?

2

Answers


  1. Chosen as BEST ANSWER

    I just found my own answer after poking around... apprently the more standard way is to use React.Children.map. Based on my original example:

    <MyComponent>
      <Hello/>
    </MyComponent>
    

    If I call this from <MyComponent>:

      React.Children.map(children, (child) => {
        console.dir(child);
      });
    

    Then I have the same object, without calling .type():

    {
      '$$typeof': Symbol(react.element),
      type: 'div',
      key: null,
      ref: null,
      props: { children: 'hello' },
      _owner: null,
      _store: {}
    }
    

  2. <div>Hello</div> is a div, <Hello/> is a function that returns a div so obviously they are not the same thing.
    <Hello/> has an empty object as props because it has no children and we didn’t pass it an attribute with a value so props is {}.

    what you want really access and clone, is the children of the parent JSX element returned by <Hello/> this has nothing to do with its props.
    the parent JSX element returned is in fact children.type() (what the function returns) this element has childrens wrapped within it (Hello) so children.type().props.children is also present there,so you can clone it.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search