简体   繁体   English

为数组子项创建唯一的键道具(React.js)

[英]Creating unique key props for array children (React.js)

I am trying to build out a component in React which takes information from a JSON source, and uses some of that information to create states which can be passed down into other separate components.我正在尝试在 React 中构建一个组件,该组件从 JSON 源获取信息,并使用其中一些信息来创建可以传递到其他单独组件的状态。 While I haven't passed my states into separate components yet, I have been able to get my state to update with the information from the JSON.虽然我还没有将我的状态传递到单独的组件中,但我已经能够让我的 state 使用来自 JSON 的信息进行更新。 However, when I load my page I get an error code which I want to sort out before continuing with my project in case there are unintended side effects from leaving the error in my code.但是,当我加载我的页面时,我会收到一个错误代码,我想在继续我的项目之前对其进行整理,以防在我的代码中留下错误产生意外的副作用。 The error code reads as following:错误代码如下:

index.js:1 Warning: Each child in a list should have a unique "key" prop. index.js:1 警告:列表中的每个孩子都应该有一个唯一的“key”道具。

Check the render method of FetchData检查FetchData的渲染方法

in div (at FetchData.js:27)在 div 中(在 FetchData.js:27)

in FetchData (at App.js:8)在 FetchData (在 App.js:8)

in div (at App.js:7)在 div 中(在 App.js:7 处)

My App.js looks like this:我的App.js看起来像这样:

import React from 'react';
import './App.css';
import FetchData from './Components/FetchData/FetchData';

function App() {
  return (
    <div className="App">
      <FetchData/>
    </div>
  );
}
export default App;

My FetchData.js looks like this:我的FetchData.js看起来像这样:

import React from 'react';

class FetchData extends React.Component {
    constructor() {
        super();
        this.state = {
            portrait: null,
            title: null
        };
    }

    componentDidMount() {
        fetch('https://randomuser.me/api')
        .then (response => {
            return response.json();
        })
        .then (data => { 
            let userImage = data.results.map((person) => {
                return (
                    <div>
                        <img alt='portrait' img src={person.picture.large}/>
                    </div>
                )
            })
            let userTitle = data.results.map((person) => {                                  //line 27
                return (
                    <div key={person.results}>
                        <div> {person.name.title} </div>
                    </div>
                )
            })
            
            this.setState ({ 
                portrait: userImage,
                title: userTitle
             })
             console.log(this.portrait, this.title)
        })
    }
    
    render() {
        return (
            <div className='box1'>
                <div className='box2'>
                    <h2>{this.state.title}</h2>
                    {this.state.portrait}
                </div>
            </div>
        )
    }
};

export default FetchData;

and just in case since my index.js looks like this:以防万一,因为我的index.js看起来像这样:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

serviceWorker.unregister();

I thought the issue was the fact that I used "person" into both my "data.results.map" so I tried to change the naming but that did not work either.我认为问题在于我在“data.results.map”中都使用了“person”,所以我尝试更改命名,但这也不起作用。 Any help would be greatly appreciated!任何帮助将不胜感激!

The error is referring to your FetchData component.该错误是指您的 FetchData 组件。

The reconciliation algorithm in React can work if you assign an unique key to returned DOM objects.如果您为返回的 DOM 对象分配一个唯一键,React 中的协调算法就可以工作。 In this case, you are returning from the map function a list of similar DOM object.在这种情况下,您将从map function 返回类似 DOM object 的列表。 Any returned chunk have to declare the key attribute on the parent node.任何返回的块都必须在父节点上声明 key 属性。

In your case:在你的情况下:

componentDidMount() {
        fetch('https://randomuser.me/api')
        .then (response => {
            return response.json();
        })
        .then (data => { 
            let userImage = data.results.map((person) => {
                return (
                    <div key={person.id}>
                        <img alt='portrait' img src={person.picture.large}/>
                    </div>
                )
            })
            let userTitle = data.results.map((person) => {                                  //line 27
                return (
                    <div key={person.id}>
                        <div> {person.name.title} </div>
                    </div>
                )
            })
            
            this.setState ({ 
                portrait: userImage,
                title: userTitle
             })
             console.log(this.portrait, this.title)
        })
    }

The key value must be an unique string and it is used by React to update the correct DOM nodes on state change.键值必须是唯一的字符串,React 使用它来更新 state 更改上的正确 DOM 节点。 (I don't know how your person.results is filled, but you need a sort of ID) (我不知道您的 person.results 是如何填写的,但您需要一种 ID)

For simple component you can also use this syntax对于简单的组件,您也可以使用此语法

            let userImage = data.results.map((person,idx) => {
                return (
                    <div key={idx}>
                        <img alt='portrait' img src={person.picture.large}/>
                    </div>
                )
            })

Be aware using this syntax, because idx is the position of the current element in the containing array, and if used more than one time, it results in duplicate keys (And React will think that nodes with same key are the same nodes)请注意使用这种语法,因为 idx 是包含数组中当前元素的 position,如果使用超过一次,会导致重复键(并且 React 会认为具有相同键的节点是相同的节点)

Using Index as a key is an anti-pattern in React.使用索引作为键是 React 中的一种反模式。

Never using the index as a key in React, unless:永远不要在 React 中使用索引作为键,除非:

  • the list and items are static–they are not computed and do not change列表和项目是静态的——它们不是计算的,也不会改变
  • the items in the list have no ids;列表中的项目没有 ID;
  • the list is never reordered or filtered.该列表永远不会重新排序或过滤。

When all of them are met, you may safely use the index as a key.当所有这些都满足时,您可以安全地使用索引作为键。

If not, please use the unique ID.如果没有,请使用唯一 ID。

It may come from the elements you are going to display,它可能来自你要展示的元素,

Or you can add a new ID property to your model or hash some parts of the content to generate a key.或者您可以将新的 ID 属性添加到您的 model 或 hash 内容的某些部分以生成密钥。 The key only has to be unique among its siblings, not globally unique.密钥只需要在其兄弟姐妹中是唯一的,而不是全局唯一的。

Read more here and here in React DocsReact Docs 中阅读更多内容

In your data.results.map((person)) function you need to add idx prop, so your code should look like:在您的 data.results.map((person)) function 中,您需要添加 idx 道具,因此您的代码应如下所示:

let userImage = data.results.map((person,idx) => {
                return (
                    <div key={idx}>
                        <img alt='portrait' img src={person.picture.large}/>
                    </div>
                )
            })

You can simply add the key attribute in the elements whenever you are using.map您可以在使用时简单地在元素中添加 key 属性。map

let userImage = data.results.map((person, index) => {
    return (
        <div key={index}>
            <img alt='portrait' img src={person.picture.large}/>
        </div>
    )
})

For the value of the key, it is preferred to use an unique id.对于键的值,最好使用唯一的 id。 If you do not have one, you can use index instead.如果没有,可以使用 index 代替。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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