bluesixty
bluesixty

Reputation: 2407

React Array converted to object when passed as a prop to SFC

I have a react function and I am passing an array of objects as a prop. When the component renders, the array is nested into an object of the same name.

Why is it being nested? And can I do something to coerce it back to an array?

Here is the code (and a link to a pen (https://codepen.io/bluesixty/pen/PJQKVq?editors=0010):

const tags = [
      {
        name: 'ios',
        link: '',
      },
      {
        name: 'ANDROID',
        link: '',
      },
      {
        name: 'REACT',
        link: '',
      },
      {
        name: 'javascript',
        link: '',
      },
    ]


const App = tagList => {

    return (
      <div>
        This is a React component!
        <ul>
          {tagList.tagList.map((tag, i) => (
            <li>
              {tag.name}
            </li>
        ))}
        </ul>
      </div>
    );
  }


ReactDOM.render(
    <App tagList={tags}/>,
  document.getElementById('root')
);

Removing the second tagList in the .map fails with 'tagList.map is not a function'. Which is true, it is an object now????

{tagList.map((tag, i) => (

Upvotes: 8

Views: 4489

Answers (2)

Joel H
Joel H

Reputation: 990

Your 1st question:

Why is it being nested?

When you pass data to any React component, you pass it as 'props'. In your case, the data you want to pass is your tags array populated with objects.

The function defining the App component has props as its parameter. When you pass your argument to it, you pass it as an object argument, i.e. props is an object containing the props you pass to a component.

That's why if you had a plain variable:

let greeting = 'Hello World'

And passed it as props:

<App content={greeting}/>

The props object would look like this:

props = {
   greeting: 'Hello World'
}

and you'd access it in the App component function as such:

{props.content}

The variable passed as an argument is an object parameter for the function.

Your 2nd question:

And can I do something to coerce it back to an array?

Yes, you can. Within the App component:

 const tags = [];
  Object.keys(props).forEach(function(prop) {
    tags.push(...props[prop]);
  });

  console.log(tags); // now an array with your tags

However, you don't need to. You can use props.tagList as mentioned in the answer above.

Hope that clears it up for others.

Upvotes: 4

Kirill Bulygin
Kirill Bulygin

Reputation: 3826

A functional component receives props as the first argument, so the correct code is:

const App = props => {

    return (
      <div>
        This is a React component!
        <ul>
          {props.tagList.map((tag, i) => (
            <li>
              {tag.name}
            </li>
        ))}
        </ul>
      </div>
    );
  }

It can also be written like this:

const App = ({ tagList }) => (
  <div>
    This is a React component!
    <ul>
      {tagList.map(({ name }, i) => (
        <li>
          {name}
        </li>
      ))}
    </ul>
  </div>
);

Upvotes: 5

Related Questions