React.js - this.props.children an object when spreading the result of a .map from the parent

Celestriel picture Celestriel · Mar 22, 2018 · Viewed 8k times · Source

I am having some strange behaviour where this.props.children is converting to an object when I spread the result of a .map() from the parent.

example:

const items = [
  { id: 1, name: "Name1" },
  { id: 2, name: "Name2" }
].map((item) => {
  return (
    <DropdownMenu_listItem key={item.id} item={item} />
  );
});

render() {
  return (
    <DropdownMenu
      label={'Some label'}
      onChange={() => {}}
    >
      {...items}
    </DropdownMenu>
  );
}

// DropdownMenu.js

render() {
  console.log(this.props.children); // {0: {…}, 1: {…}}

  return (
    // ...
  );
}

The weird part is that when I omit the .map() and pass the elements directly, they appear in this.props.children as an array like expected:

render() {
  return (
    <DropdownMenu
      label={'Some label'}
      onChange={() => {}}
    >
      <DropdownMenu_listItem item={{...}} />
      <DropdownMenu_listItem item={{...}} />
    </DropdownMenu>
  );
}

// DropdownMenu.js

render() {
  console.log(this.props.children); // [{…}, {…}]

  return (
    // ...
  );
}

Any insight into why this is happening would be greatly appreciated.

Answer

Shubham Khatri picture Shubham Khatri · Mar 22, 2018

Its not because of map that you get children as object, but because you use spread operator for the items in

<DropdownMenu
          label={'Some label'}
          onChange={() => {}}
        >
          {...items} {/*spread operator here */}
</DropdownMenu>

Now that after map items is an array using {...items } makes it an object since you wrap your result of spread operator with {}, If you write {items}, that will be fine

 <DropdownMenu
      label={'Some label'}
      onChange={() => {}}
    >
      {items}
 </DropdownMenu>