简体   繁体   中英

ReactJS - Passing an element of an array of Objects as props

I am building aReact Application.I have a state array which holds array of blogs. I am rendering each blog using a BlogDisplay component. Following is my code :

render() {
        for( var i = 0;i < this.state.blogData.length;i++){
            blogDataToRender.push(<BlogDisplay blogData = {this.state.blogData[i]} onUserTriggerForDetailedView ={this.props.onUserTriggerForDetailedView}/>);
        }
        return (
            <div>
                {blogDataToRender}
            </div>
        );
    }

I am getting a warning like this :

index.js:5279 Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `BloggerHome`. See https://facebook.github.io/react/docs/lists-and-keys.html#keys for more information.
in BlogDisplay (created by BloggerHome)
in BloggerHome (created by Blogger)
in div (created by Blogger)
in div (created by Blogger)
in Blogger

Is my modelling correct ? How can I correct this?

Thanks a lot.

You need to add a key for each BlogDisplay component:

for( var i = 0;i < this.state.blogData.length;i++){
    blogDataToRender.push(<BlogDisplay key={i} blogData = {this.state.blogData[i]} onUserTriggerForDetailedView ={this.props.onUserTriggerForDetailedView}/>);
}

The key is important for child components in an array. Because when one of those child components is under operation, React needs the key to determine which one is operated. Also, when the source array data is changed, React needs the key to check the diff of components.

For in-depth explanation about why keys are necessary, please refer to the official document .

What should be the value of key for each child component?

According to the above document:

The key only has to be unique among its siblings, not globally unique.

Also, blogData[i].id is the best choice if there is a unique id in the source data. Indexes as in the above example is not recommended, if the child components would reorder (performance issue).

Each element in React needs to have a unique key, which React uses to identify it. When you just render an element overtly, React automatically assigns one. However, when you assign an ARRAY of elements, each element in that array isn't assigned a key by default, so you need to. Something like this:

blogDataToRender.push(<BlogDisplay key={i} blogData={this.state.blogData[i]} onUserTriggerForDetailedView={this.props.onUserTriggerForDetailedView}/>);

Check out Chris' reply on Understanding unique keys for array children in React.js .

To fix this, you must set a unique id for each of your elements and then add a key prop to each element. You can read more about how React uses keys to identify elements in lists in the official documentation .

This is how your render() method should look:

render() {
    return (
        <div>
            {this.state.blogData.map((item) => {
                return (<BlogDisplay key={item.id} blogData={item} onUserTriggerForDetailedView={this.props.onUserTriggerForDetailedView} />)
            })}
        </div>
    );
}

To answer your question quickly all you need to do is read the error and fix it! Add a unique key value to each component like so:

...
  for( var i = 0;i < this.state.blogData.length;i++){
    blogDataToRender.push(
      <BlogDisplay
        key={this.state.blogData[i].id}
        blogData={this.state.blogData[i]}
        onUserTriggerForDetailedView{this.props.onUserTriggerForDetailedView}
     />
    );
  }
...

In this case I assume that each one of your blog entries has a unique id, the thing you need to be aware of here is that the key value needs to be unique and not depending on the position of that element inside the array. Every time you render these elements that key needs to be the same, this value is used by React to optimize re rendering and avoid rendering items that did not change. If you want to understand why this is necessary here is a good link . Next time I recommend reading the docs because they are very well done and you can learn a lot from it.

Now the way I would do it is using map :

...
  const blogDataToRender = this.state.blogData.map(blogData => 
      <BlogDisplay
        key={blogData.id}
        blogData={blogData}
        onUserTriggerForDetailedView{this.props.onUserTriggerForDetailedView}
     />
    );
...

This helps readability and leverages an iterator so you don't need to keep track of the index. It is a widely used pattern when developing in React.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM