8

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.

Celestriel
  • 327
  • 1
  • 5
  • 10

2 Answers2

7

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>
Shubham Khatri
  • 246,420
  • 52
  • 367
  • 373
  • But OP mentioned that if he removes the `map` functionality then he is getting the array. As per your answer both the cases he should get object. is that correct? – Suresh Ponnukalai Mar 22 '18 at 06:38
  • 2
    @SureshPonnukalai In the second case he is manually adding ` ` as children and not using spread operator – Shubham Khatri Mar 22 '18 at 06:40
6

{...items} is passed as childrens in DropdownMenu.js.

Its available as a this.props.children

this.props.children can be array or object depend on how you rendering the children elements.

in your case

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

items is an array. As we know

array is also type of object in javascript

with key equal to element's index and value is element itself

{...items} : this will passed as a object with key as a element index and value equal to array element.

To fix your problem, you should passed it without using spread operator.

{items} : this will passed as an array.

<DropdownMenu
      label={'Some label'}
      onChange={() => {}}
    >
      {items}
</DropdownMenu>
RIYAJ KHAN
  • 14,597
  • 5
  • 30
  • 52
  • I was previously using { ...children } which didn't work so, I used { this.props.children } and it worked like a charm! – Sajid2405 Mar 15 '21 at 14:01