gpt4 book ai didi

Understanding unique keys for array children in React.js(了解React.js中数组子对象的唯一键)

转载 作者:bug小助手 更新时间:2023-10-24 17:55:05 29 4
gpt4 key购买 nike



I'm building a React component that accepts a JSON data source and creates a sortable table.

Each of the dynamic data rows has a unique key assigned to it but I'm still getting an error of:

我正在构建一个Reaction组件,该组件接受JSON数据源并创建一个可排序的。每个动态数据行都有一个分配给它的唯一键,但我仍然收到以下错误:




Each child in an array should have a unique "key" prop.

Check the render method of TableComponent.




My TableComponent render method returns:

我的TableComponent呈现方法返回:



<table>
<thead key="thead">
<TableHeader columns={columnNames}/>
</thead>
<tbody key="tbody">
{ rows }
</tbody>
</table>


The TableHeader component is a single row and also has a unique key assigned to it.

TableHeader组件是单行,并为其分配了唯一的键。



Each row in rows is built from a component with a unique key:

行中的每一行都是从具有唯一键的组件构建的:



<TableRowItem key={item.id} data={item} columns={columnNames}/>


And the TableRowItem looks like this:

TableRowItem如下所示:



var TableRowItem = React.createClass({
render: function() {

var td = function() {
return this.props.columns.map(function(c) {
return <td key={this.props.data[c]}>{this.props.data[c]}</td>;
}, this);
}.bind(this);

return (
<tr>{ td(this.props.item) }</tr>
)
}
});


What is causing the unique key prop error?

导致唯一键道具错误的原因是什么?


更多回答

Your rows in JS array should have unique key property. It'll help ReactJS to find references to the appropriate DOM nodes and update only content inside mark-up but not re-render the whole table/row.

JS数组中的行应具有唯一的键属性。它将帮助ReactJS找到对适当DOM节点的引用,并且只更新标记内的内容,而不重新呈现整个表/行。

Can you also share rows array or more preferably a jsfiddle? You dont need a key property on thead and tbody by the way.

您还可以共享行数组或更好的jsfiddle吗?顺便说一句,您不需要Head和TBody上的键属性。

I added the row component to the original question @nilgun.

我在原来的问题@Nilgan中添加了行组件。

Is it possible that some items do not have an id or have same id?

有没有可能某些物品没有ID或具有相同的ID?

优秀答案推荐

You should add a key to each child as well as each element inside children.

您应该为每个子项以及子项中的每个元素添加一个键。


This way React can handle the minimal DOM change.

这种方式的Reaction可以处理最小的DOM更改。


In your code, each <TableRowItem key={item.id} data={item} columns={columnNames}/> is trying to render some children inside them without a key.

在您的代码中,每个 都试图在没有键的情况下呈现它们内部的一些子项。


Check this example.

请查看此示例。


Try removing the key={i} from the <b></b> element inside the div's (and check the console).

尝试从div的元素中删除键={i}(并检查控制台)。


In the sample, if we don't give a key to the <b> element and we want to update only the object.city, React needs to re-render the whole row vs just the element.

在样例中,如果我们没有给元素一个键,并且我们只想更新对象。City,那么Reaction需要重新呈现整个行,而不是元素。


Here is the code:

以下是代码:


const data = [
{ name: "Nuri", age: 28, city: "HO" },
{ name: "Talib", age: 82, city: "HN" },
{ name: "Jenny", age: 41, city: "IT" },
];

const ExampleComponent = React.createClass({
render: function () {
const infoData = this.props.info;
return (
<div>
{infoData.map((object, i) => {
return (
<div className={"row"} key={i}>
{[
object.name,
// remove the key
<b className="fosfo" key={i}>
{" "}
{object.city}{" "}
</b>,
object.age,
]}
</div>
);
})}
</div>
);
},
});

React.render(<ExampleComponent info={data} />, document.body);



The answer posted by @Chris at the bottom goes into much more detail than this answer.


React documentation on the importance of keys in reconciliation: Keys

关于关键字在协调中的重要性的Reaction文档:关键字



Be careful when iterating over arrays!!

在迭代数组时要小心!!


It is a common misconception that using the index of the element in the array is an acceptable way of suppressing the error you are probably familiar with:

一种常见的误解是,使用数组中元素的索引是消除您可能熟悉的错误的一种可接受的方式:


Each child in an array should have a unique "key" prop.

However, in many cases it is not! This is anti-pattern that can in some situations lead to unwanted behavior.

然而,在许多情况下,它并不是!这是反模式,在某些情况下可能会导致不想要的行为。




Understanding the key prop


React uses the key prop to understand the component-to-DOM Element relation, which is then used for the reconciliation process. It is therefore very important that the key always remains unique, otherwise there is a good chance React will mix up the elements and mutate the incorrect one. It is also important that these keys remain static throughout all re-renders in order to maintain best performance.

React使用关键道具来理解组件到DOM元素的关系,然后将其用于协调过程。因此,关键字始终保持唯一是非常重要的,否则,Reaction很有可能会混淆元素并使不正确的元素发生突变。同样重要的是,为了保持最佳性能,这些关键点在所有重新渲染过程中保持不变。


That being said, one does not always need to apply the above, provided it is known that the array is completely static. However, applying best practices is encouraged whenever possible.

也就是说,只要知道该数组是完全静态的,就不需要总是应用上述方法。但是,只要有可能,就鼓励应用最佳做法。


A React developer said in this GitHub issue:

一位Reaction开发人员在GitHub的这一期中表示:




  • key is not really about performance, it's more about identity (which in turn leads to better performance). randomly assigned and changing values are not identity

  • We can't realistically provide keys [automatically] without knowing how your data is modeled. I would suggest maybe using some sort of hashing function if you don't have ids

  • We already have internal keys when we use arrays, but they are the index in the array. When you insert a new element, those keys are wrong.



In short, a key should be:

简而言之,关键应该是:



  • Unique - A key cannot be identical to that of a sibling component.

  • Static - A key should not ever change between renders.




Using the key prop


As per the explanation above, carefully study the following samples and try to implement, when possible, the recommended approach.

根据上面的解释,请仔细研究以下示例,并在可能的情况下尝试实现推荐的方法。




Bad (Potentially)


<tbody>
{rows.map((row, i) => {
return <ObjectRow key={i} />;
})}
</tbody>

This is arguably the most common mistake seen when iterating over an array in React. This approach isn't technically "wrong", it's just... "dangerous" if you don't know what you are doing. If you are iterating through a static array then this is a perfectly valid approach (e.g. an array of links in your navigation menu). However, if you are adding, removing, reordering or filtering items, then you need to be careful. Take a look at this detailed explanation in the official documentation.

这可以说是在Reaction中迭代数组时最常见的错误。这种方法从技术上讲并不是“错误的”,只是...如果你不知道自己在做什么,那就是“危险”。如果您正在迭代一个静态数组,那么这是一个非常有效的方法(例如,导航菜单中的一个链接数组)。但是,如果您要添加、删除、重新排序或筛选项目,则需要小心。请看官方文件中的这一详细解释。




class MyApp extends React.Component {
constructor() {
super();
this.state = {
arr: ["Item 1"]
}
}

click = () => {
this.setState({
arr: ['Item ' + (this.state.arr.length+1)].concat(this.state.arr),
});
}

render() {
return(
<div>
<button onClick={this.click}>Add</button>
<ul>
{this.state.arr.map(
(item, i) => <Item key={i} text={"Item " + i}>{item + " "}</Item>
)}
</ul>
</div>
);
}
}

const Item = (props) => {
return (
<li>
<label>{props.children}</label>
<input value={props.text} />
</li>
);
}

ReactDOM.render(<MyApp />, document.getElementById("app"));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>




In this snippet we are using a non-static array and we are not restricting ourselves to using it as a stack. This is an unsafe approach (you'll see why). Note how as we add items to the beginning of the array (basically unshift), the value for each <input> remains in place. Why? Because the key doesn't uniquely identify each item.

在这段代码中,我们使用的是非静态数组,我们并不局限于将其用作堆栈。这是一种不安全的方法(你会明白为什么)。请注意,当我们将项添加到数组的开头时(基本上是取消移位),每个的值保持不变。为什么?因为密钥并不唯一地标识每一项。


In other words, at first Item 1 has key={0}. When we add the second item, the top item becomes Item 2, followed by Item 1 as the second item. However, now Item 1 has key={1} and not key={0} anymore. Instead, Item 2 now has key={0}!!

换句话说,第一项1具有键={0}。当我们添加第二项时,顶部项变为项2,紧随其后的是项1作为第二项。但是,现在项1具有key={1},而不再具有key={0}。相反,项目2现在的密钥为{0}!!


As such, React thinks the <input> elements have not changed, because the Item with key 0 is always at the top!

因此,Reaction认为元素没有更改,因为键为0的项始终在顶部!


So why is this approach only sometimes bad?

那么,为什么这种方法只是有时不好呢?


This approach is only risky if the array is somehow filtered, rearranged, or items are added/removed. If it is always static, then it's perfectly safe to use. For example, a navigation menu like ["Home", "Products", "Contact us"] can safely be iterated through with this method because you'll probably never add new links or rearrange them.

只有在以某种方式过滤、重新排列数组或添加/删除项时,这种方法才有风险。如果它始终是静态的,那么使用它是完全安全的。例如,使用此方法可以安全地迭代像[“Home”、“Products”、“Contact Us”]这样的导航菜单,因为您可能永远不会添加新链接或重新排列它们。


In short, here's when you can safely use the index as key:

简而言之,下面是您可以安全地使用索引作为键的时候:



  • The array is static and will never change.

  • The array is never filtered (display a subset of the array).

  • The array is never reordered.

  • The array is used as a stack or LIFO (last in, first out). In other words, adding can only be done at the end of the array (i.e push), and only the last item can ever be removed (i.e pop).


Had we instead, in the snippet above, pushed the added item to the end of the array, the order for each existing item would always be correct.

相反,如果我们在上面的代码片断中将添加的项推到数组的末尾,则每个现有项的顺序将始终正确。




Very bad


<tbody>
{rows.map((row) => {
return <ObjectRow key={Math.random()} />;
})}
</tbody>

While this approach will probably guarantee uniqueness of the keys, it will always force react to re-render each item in the list, even when this is not required. This a very bad solution as it greatly impacts performance. Not to mention that one cannot exclude the possibility of a key collision in the event that Math.random() produces the same number twice.

虽然这种方法可能会保证键的唯一性,但它始终会强制Reaction重新呈现列表中的每一项,即使这不是必需的。这是一个非常糟糕的解决方案,因为它极大地影响了性能。更不用说,如果Math.Ranic()两次生成相同的数字,则不能排除密钥冲突的可能性。



Unstable keys (like those produced by Math.random()) will cause many component instances and DOM nodes to be unnecessarily recreated, which can cause performance degradation and lost state in child components.





Very good


<tbody>
{rows.map((row) => {
return <ObjectRow key={row.uniqueId} />;
})}
</tbody>

This is arguably the best approach because it uses a property that is unique for each item in the dataset. For example, if rows contains data fetched from a database, one could use the table's Primary Key (which typically is an auto-incrementing number).

这可以说是最好的方法,因为它使用的属性对于数据集中的每一项都是唯一的。例如,如果行包含从数据库提取的数据,则可以使用表的主键(通常是自动递增的数字)。



The best way to pick a key is to use a string that uniquely identifies a list item among its siblings. Most often you would use IDs from your data as keys





Good


componentWillMount() {
let rows = this.props.rows.map(item => {
return {uid: SomeLibrary.generateUniqueID(), value: item};
});
}

...

<tbody>
{rows.map((row) => {
return <ObjectRow key={row.uid} />;
})}
</tbody>

This is also a good approach. If your dataset does not contain any data that guarantees uniqueness (e.g. an array of arbitrary numbers), there is a chance of a key collision. In such cases, it is best to manually generate a unique identifier for each item in the dataset before iterating over it. Preferably when mounting the component or when the dataset is received (e.g. from props or from an async API call), in order to do this only once, and not each time the component re-renders. There are already a handful of libraries out there that can provide you such keys. Here is one example: react-key-index.

这也是一个很好的方法。如果您的数据集不包含任何保证唯一性的数据(例如,任意数字的数组),则存在键冲突的可能性。在这种情况下,最好在迭代数据集中的每一项之前为其手动生成唯一的标识符。优选地,当安装组件时或当接收到数据集时(例如,从道具或从异步API调用),以便仅执行一次,而不是每次组件重新呈现。已经有几个库可以为您提供这样的密钥。这里有一个例子:reaction-key-index。



This may or not help someone, but it might be a quick reference. This is also similar to all the answers presented above.

这可能对某些人有帮助,也可能没有帮助,但它可能是一个快速参考。这也与上面给出的所有答案类似。


I have a lot of locations that generate list using the structure below:

我有很多使用以下结构生成列表的位置:


return (
{myList.map(item => (
<>
<div class="some class">
{item.someProperty}
....
</div>
</>
)}
)


After a little trial and error (and some frustrations), adding a key property to the outermost block resolved it. Also, note that the <> tag is now replaced with the <div> tag now.

在经历了一些试错(和一些挫折)之后,向最外层的块添加一个关键属性解决了这个问题。另外,请注意,<>标记现在被

标记替换。


return (

{myList.map((item, index) => (
<div key={index}>
<div class="some class">
{item.someProperty}
....
</div>
</div>
)}
)

Of course, I've been naively using the iterating index (index) to populate the key value in the above example. Ideally, you'd use something which is unique to the list item.

当然,在上面的例子中,我很天真地使用迭代索引(Index)来填充键值。理想情况下,您应该使用列表项独有的内容。



Check: key = undef !!!

检查:key=undef!



You got also the warn message:

您还收到了警告消息:



Each child in a list should have a unique "key" prop.


if your code is complete right, but if on

如果您的代码是完全正确的,但如果



<ObjectRow key={someValue} />


someValue is undefined!!! Please check this first. You can save hours.

未定义某个值!请先把这个检查一下。你可以节省几个小时。



Here are the React docs that explain well using the Key property, the key should be defined at the parent component it should not be used inside the child component.React Docs

以下是使用Key属性很好地解释的Reaction文档,键应该在父组件上定义,它不应该在子组件内使用。


enter image description here


enter image description here



You should use a unique value for each children key of tbody where

您应该为tbody的每个子键使用唯一的值,其中



  • the value cannot not be identical (same) to its sibling

  • should not change between renders


For example, the key value can be database id or UUID (Universal Unique Identifier).

例如,密钥值可以是数据库ID或UUID(统一唯一标识符)。


Here the keys are handling manually:

这里的密钥是手动处理的:


<tbody>
{rows.map((row) => <ObjectRow key={row.uuid} />)}
</tbody>

You can also let React handle the keys using React.Children.toArray

您还可以让Reaction使用React.Children.toArray处理密钥


<tbody>
{React.Children.toArray(rows.map((row) => <ObjectRow />))}
</tbody>


Just add the unique key to the your Components

只需将唯一密钥添加到您的组件



data.map((marker)=>{
return(
<YourComponents
key={data.id} // <----- unique key
/>
);
})


Warning: Each child in an array or iterator should have a unique "key" prop.

警告:数组或迭代器中的每个子级都应该有一个唯一的“key”道具。



This is a warning as for array items which we are going to iterate over will need a unique resemblance.

这是一个警告,因为我们将要迭代的数组项将需要唯一的相似性。



React handles iterating component rendering as arrays.

React处理将组件呈现为数组的迭代。



Better way to resolve this is provide index on the array items you are going to iterate over.for example:

解决此问题的更好方法是为要迭代的数组项提供索引。例如:



class UsersState extends Component
{
state = {
users: [
{name:"shashank", age:20},
{name:"vardan", age:30},
{name:"somya", age:40}
]
}
render()
{
return(
<div>
{
this.state.users.map((user, index)=>{
return <UserState key={index} age={user.age}>{user.name}</UserState>
})
}
</div>
)
}


index is React built-in props.

索引是Reaction内置的道具。



When you don’t have stable IDs for rendered items, you may use the item index as a key as a last resort:

当您没有用于呈现项的稳定ID时,您可以将项索引作为键作为最后的手段:


const todoItems = todos.map((todo, index) =>
// Only do this if items have no stable IDs
<li key={index}>
{todo.text}
</li>
);

Please refer to List and Keys - React

请参阅列表和关键字-反应



In ReactJS if you are rendering an array of elements you should have a unique key for each those elements. Normally those kinda situations are creating a list.

在ReactJS中,如果要呈现一个元素数组,则每个元素都应该有一个唯一的键。通常情况下,这些情况会形成一份清单。


Example:

示例:


function List() {
const numbers = [0,1,2,3];

return (
<ul>{numbers.map((n) => <li> {n} </li>)}</ul>
);
}

ReactDOM.render(
<List />,
document.getElementById('root')
);

In the above example, it creates a dynamic list using li tag, so since li tag does not have a unique key it shows an error.

在上面的例子中,它使用li标记创建了一个动态列表,因此由于li标记没有唯一的键,所以它显示了一个错误。


After fixed:

修复后:


function List() {
const numbers = [0,1,2,3];

return (
<ul>{numbers.map((n) => <li key={n}> {n} </li>)}</ul>
);
}

ReactDOM.render(
<List />,
document.getElementById('root')
);

Alternative solution when use map when you don't have a unique key (this is not recommended by react eslint ):

当您没有唯一密钥时使用map时的替代解决方案(Reaction eslint不推荐这样做):


function List() {
const numbers = [0,1,2,3,4,4];

return (
<ul>{numbers.map((n,i) => <li key={i}> {n} </li>)}</ul>
);
}

ReactDOM.render(
<List />,
document.getElementById('root')
);

Live example: https://codepen.io/spmsupun/pen/wvWdGwG

现场示例:https://codepen.io/spmsupun/pen/wvWdGwG



Best solution of define unique key in react:
inside the map you initialized the name post then key define by key={post.id} or in my code you see i define the name item then i define key by key={item.id}:

在Reaction中定义唯一键的最佳解决方案:在映射中初始化名称POST,然后通过key={post.id}定义键,或者在我的代码中,您可以看到我定义了名称Item,然后通过key={item.id}定义键:





<div className="container">
{posts.map(item =>(

<div className="card border-primary mb-3" key={item.id}>
<div className="card-header">{item.name}</div>
<div className="card-body" >
<h4 className="card-title">{item.username}</h4>
<p className="card-text">{item.email}</p>
</div>
</div>
))}
</div>





If we have array object data . then we map to show the data . and pass the unique id (key = {product.id} ) because browser can select the unique data.

如果我们有数组对象数据。然后我们绘制地图以显示数据。并传递唯一id(key={Product.id}),因为浏览器可以选择唯一的数据。


example : [
{
"id": "1",
"name": "walton glass door",
"suplier": "walton group",
"price": "50000",
"quantity": "25",
"description":"Walton Refrigerator is the Best Refrigerator brand in bv
Bangladesh "
},
{

"id": "2",
"name": "walton glass door",
"suplier": "walton group",
"price": "40000",
"quantity": "5",
"description":"Walton Refrigerator is the Best Refrigerator brand in
Bangladesh "
},
}

now we are mapping the data and pass the unique id:

现在我们正在映射数据并传递唯一的id:


{
products.map(product => <product product={product} key={product.id}
</product>)
}


I was running into this error message because of <></> being returned for some items in the array when instead null needs to be returned.

我遇到这个错误消息是因为数组中的某些项返回了<>,而实际上需要返回NULL。



I had a unique key, just had to pass it as a prop like this:

我有一把独一无二的钥匙,只是必须像这样把它当作道具来传递:


<CompName key={msg._id} message={msg} />

This page was helpful:

这个页面很有帮助:


https://reactjs.org/docs/lists-and-keys.html#keys

Https://reactjs.org/docs/lists-and-keys.html#keys



In my case, set id to tag

在我的例子中,将id设置为tag


<tbody key={i}>

The problem is solved.

问题解决了。



A visual explanation.

一个直观的解释。



  1. The incorrect way key=index (of an array)


enter image description here


As you can see, label 3, label 2, and label 1 ALL got re-rendered (flashing in the Elements panel).

如您所见,Label 3、Label 2和Label 1都被重新渲染(在元素面板中闪烁)。



  1. The correct way key=uniqueId
    enter image description here


Only the top new element flashes (gets re-rendered).

只有顶部的新元素闪烁(重新呈现)。



This is a warning, But addressing this will make Reacts rendering much FASTER,

这是一个警告,但解决此问题将使反应渲染速度更快,



This is because React needs to uniquely identify each items in the list. Lets say if the state of an element of that list changes in Reacts Virtual DOM then React needs to figure out which element got changed and where in the DOM it needs to change so that browser DOM will be in sync with the Reacts Virtual DOM.

这是因为Reaction需要唯一地标识列表中的每一项。比方说,如果该列表中某个元素的状态在REACTS虚拟DOM中发生了更改,那么REACTION需要找出哪个元素发生了更改,以及它需要在DOM中的什么位置进行更改,以便浏览器DOM与REACTS虚拟DOM同步。



As a solution just introduce a key attribute to each li tag. This key should be a unique value to each element.

作为解决方案,只需为每个li标记引入一个键属性即可。该键对于每个元素都应该是唯一的值。



var TableRowItem = React.createClass({
render: function() {

var td = function() {
return this.props.columns.map(function(c, i) {
return <td key={i}>{this.props.data[c]}</td>;
}, this);
}.bind(this);

return (
<tr>{ td(this.props.item) }</tr>
)
}
});


This will sove the problem.

这将解决这个问题。



If you are getting error like :

> index.js:1 Warning: Each child in a list should have a unique "key" prop.

Check the render method of `Home`. See https://reactjs.org/link/warning-keys for more information.

Then Use inside map function like:

{classes.map((user, index) => (
<Card **key={user.id}**></Card>
))}`enter code here`


This is a simple example,I have used a react condition with && first then map, in the I have added the key the user id to be sure that it's unique

这是一个简单的示例,我使用了一个带有&&的反应条件,首先是映射,然后在中添加了键用户ID,以确保它是唯一的


 <tbody>
{users &&
users.map((user) => {
return <tr key={user._id}>
<td>{user.username}</td>
<td><input
name="isGoing"
type="checkbox"
checked={user.isEnabled}
onChange={handleInputChangeNew}/></td>
<td>{user.role.roleTitle} - {user.role.department.departmentName}</td>
{/*<td className="text-right">
<Button>
ACTION
</Button>
</td>*/}
</tr>
})
}


</tbody>


your key should be unique.like an unique id.And your code should be like this

您的密钥应该是唯一的。例如唯一的ID。您的代码应该是这样的


<div>
{products.map(product => (
<Product key={product.id}>
</Product>
))}
</div>


According to React docs, each row/item should have a unique key.

根据Reaction文档,每一行/项都应该有一个唯一的键。



Keys help React identify which items have changed, are added, or are removed.



Personally, I prefer using the crypto interface to generate a random UUID:

(crypto is built-in in vanilla-js)

就我个人而言,我更喜欢使用加密接口来生成随机的UUID:(加密是内置在vanilla-js中的)


const numbers = [1, 2, 3, 4, 5];

const listItems = numbers.map((number) =>
<li key={crypto.randomUUID()}>item {number}
</li>
);


I think when working with tables (or in similar examples), creating a unique key should be passed to the child component from the parent component for the sake of REUSABILITY.

我认为在使用表时(或在类似的示例中),出于可重用性的考虑,应该将唯一键从父组件传递给子组件。


Because if you are creating a table, that means you are passing data from the parent. If you assign key={row.name} maybe currently data has name property but if you want to use this table component somewhere else you assume that in each row of data that you have passed, you have name property.

因为如果您正在创建表,这意味着您将从父级传递数据。如果您指定key={row.name},则可能当前数据具有Name属性,但如果您希望在其他地方使用该表组件,则假定在您传递的每一行数据中都具有Name属性。


Since the engineer will be preparing the data in the parent component, the engineer should create a key function based on the data.

由于工程师将在父组件中准备数据,因此工程师应根据数据创建关键功能。


const keyFunc = (student) => {
return student.id;
};

In this case, the engineer knows what data it is sending, it knows that each row has an id property that is unique. Maybe in the different data set, the data set is stock prices and it does not have "id" property but "symbol"

在这种情况下,工程师知道它要发送什么数据,它知道每一行都有一个唯一的id属性。也许在不同的数据集中,数据集是股票价格,它没有“id”属性,而是“符号”。


 const keyFunc = (stock) => {
return stock.symbol;
};

this keyFunc should be passed to the child component as a prop to guarantee reusability and uniqueness.

这个keyFunc应该作为道具传递给子组件,以保证可重用性和唯一性。



I don't go with the detail explanation but the key to this answer is "key"
just put the key attribute in your tag and ensure that every-time you iterate you give unique value to it

我不支持详细的解释,但这个答案的关键是“key”只需将key属性放入您的标记中,并确保每次迭代时都赋予它唯一的值


#ensure that the key's value is not clashing with others

#确保密钥的值不与其他密钥冲突


Example

示例


<div>
{conversation.map(item => (
<div key={item.id } id={item.id}>
</div>
))}
</div>

where the conversation is an array of something like below :

其中,对话是一组类似以下内容的内容:


  const conversation = [{id:"unique"+0,label:"OPEN"},{id:"unique"+1,label:"RESOLVED"},{id:"unique"+2,label:"ARCHIVED"},
]


I've seen many times people rendering fragments <></> and it generates this issue. Try to change the fragments to null or a component with a unique key

我见过很多次人们渲染碎片<>,这就产生了这个问题。尝试将片段更改为空或具有唯一键的组件




If you are struggling with this error Each child in a list should have a unique "key" prop.




Solve by declaring index value to the key attribute inside the rendering element.




App.js component



import Map1 from './Map1';

const arr = [1,2,3,4,5];

const App = () => {
return (
<>

<Map1 numb={arr} />

</>
)
}

export default App


Map.js component



const Map1 = (props) => {

let itemTwo = props.numb;
let itemlist = itemTwo.map((item,index) => <li key={index}>{item}</li>)

return (
<>
<ul>
<li style={liStyle}>{itemlist}</li>
</ul>
</>
)
}

export default Map1


The "Each child in a list should have a unique "key" prop." warning happens in React when you create a list of elements without the special key attribute. Keys must be assigned to each element in a loop to give stable identity to elements in React.

列表中的每个孩子都应该有一个唯一的关键道具。当您创建一个没有特殊键属性的元素列表时,Reaction中会出现警告。必须将关键点指定给循环中的每个元素,才能为Reaction中的元素提供稳定的标识。


We can set the id property of the object as a unique key.

我们可以将对象的id属性设置为唯一键。


export default function App() {
const posts = [
{ id: 1, title: "First "},
{ id: 2, title: "Second" },
{ id: 3, title: "Third" }
];
return (
<div>
<ul>
{posts.map(value =>
<li key={value.id}>{value.title}</li>
)}
</ul>
</div>
);}


//simple way

//if u using ant design remove the empty fragment...

//worng ans---> change to following crt ans

export default function App() {
const posts = [
{ id: 1, title: "First "},
{ id: 2, title: "Second" },
{ id: 3, title: "Third" }
];
{fields.map((field,index)=>{
return(
<> //empty fragment
<Row key={index}>
<Col span={6}>hello</Col>
</Row>
</>
)
})}

//correct ans
//remove the empty fragments after solve this key.prop warning problem
export default function App() {
const posts = [
{ id: 1, title: "First "},
{ id: 2, title: "Second" },
{ id: 3, title: "Third" }
];
{fields.map((field,index)=>{
return(
<> //empty fragment
<Row key={index}>
<Col span={6}>hello</Col>
</Row>
</>
)
})}


I faced a similar problem but not exact. Tried every possible solution and couldn't get rid of that error

我也遇到过类似的问题,但不是很准确。尝试了所有可能的解决方案,但无法摆脱该错误



Each child in an array should have a unique "key" prop.



Then I tried opening it in a different local host. I don't know how, but it worked!

然后我试着在不同的本地主机上打开它。我不知道是怎么回事,但它奏效了!


更多回答

I am running into the exact same error. Was this resolved after the chat? If so, can you please post an update to this question.

我也遇到了完全相同的错误。聊天后这件事解决了吗?如果是这样的话,你能不能更新一下这个问题。

Why is is so hard for React to generate unique keys itself?

为什么Reaction自己很难生成唯一的密钥?

@DavorLucic, here is a discussion: github.com/facebook/react/issues/1342#issuecomment-39230939

@DavorLucic,这里有一个讨论:github.com/facebook/react/issues/1342#issuecomment-39230939

This is pretty much the official word on a note made in the issue chat linked to above: keys are about identity of a member of a set and auto-generation of keys for items emerging out of an arbitrary iterator probably has performance implications within the React library.

这几乎是上面链接的问题聊天中笔记上的官方词汇:键是关于集合中成员的身份的,并且为从任意迭代器中出现的项自动生成键可能会在Reaction库中影响性能。

Is there documentation explaining why not only the child nodes need a unique key, but also the children of those child nodes? I couldn't find anything about that specifically in the docs.

是否有文档解释为什么不仅子节点需要唯一键,而且这些子节点的子节点也需要唯一键?我在文件里找不到任何关于这一点的具体信息。

In the official docs, they use toString() to convert to string instead of leaving as number. Is this important to remember?

在官方文档中,他们使用toString()来转换为字符串,而不是将其保留为数字。记住这一点重要吗?

@skube, no, you can use integers as key as well. Not sure why they are converting it.

@Skube,不,也可以使用整数作为key。不知道他们为什么要改装。

@skube, yes that is perfectly acceptable. As stated in the examples above, you can use the item's index of the iterated array (and that's an integer). Even the docs state: "As a last resort, you can pass item's index in the array as a key". What happens though is that the key always ends up being a String anyway.

@Skube,是的,这是完全可以接受的。如上面的示例所述,您可以使用迭代数组的项索引(这是一个整数)。即使是文档也声明:“作为最后的手段,您可以将项的索引作为键传递到数组中”。但是,无论如何,关键字最终都会是一个字符串。

should this key be unique only in that array or should be unique in the whole App?

该密钥应该只在该数组中唯一,还是应该在整个应用程序中唯一?

@farmcommand2, keys are applied to React Components, and need to be unique among siblings. This is stated above. In other words, unique in the array

@FARM命令2,密钥被应用于反应组件,并且在同级中需要是唯一的。这一点如上所述。换句话说,在数组中是唯一的

This was extremely helpful, thank you! I didn't even realize I had to put it in the outermost layer

这是非常有帮助的,谢谢!我甚至没有意识到我必须把它放在最外面的一层

I was doing similar groupings, but with table rows. You cannot wrap a table row in a div. Instead, wrap it in a react Fragment with a key, as demonstrated here: stackoverflow.com/a/51875412/750914

我正在进行类似的分组,但使用的是表行。不能在div中换行。相反,将其包装在带有键的反应片段中,如下所示:Stackoverflow.com/a/51875412/750914

<> is a short syntax for <React.Fragment>. So if you want to add a key you can do like this: <React.Fragment key={item.id}>

<>是的简短语法。因此,如果您想要添加密钥,可以这样做:

I had the same issue using Material-UI where I was using a List (and elsewhere a Menu) and placing the child items of those components inside a Tooltip. Giving the Tooltip the "key" instead of the ListItem/MenuItem itself got rid of the warning.

我在使用MATERIAL-UI时遇到了同样的问题,我在其中使用了一个列表(在其他地方使用了一个菜单),并将这些组件的子项放在了工具提示中。给工具提示“键”而不是ListItem/MenuItem本身可以消除警告。

Thank you, removing the empty tag (added for convenience) solved it.

谢谢,删除空标签(为了方便而添加)解决了这个问题。

literally saved!

真的得救了!

While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review

虽然这个链接可能会回答这个问题,但最好在这里包括答案的基本部分,并提供链接以供参考。如果链接的页面发生更改,仅限链接的答案可能会无效。-摘自评论

The key data.id can't possibly be unique among the YourComponents.

键data.id在YourComponents中不可能是唯一的。

This approach is potentially dangerous if the items are rearranged somehow. But if they remain static then this is fine.

如果以某种方式重新排列项目,这种方法可能会有危险。但如果它们保持不变,那么这是很好的。

@chris I completely agree with you because in this case index may be duplicated. Better to use dynamic values for key.

@Chris我完全同意您的观点,因为在这种情况下,索引可能会重复。最好对键使用动态值。

@chris I also agree with your comment. We should use dynamic values rather then index because there may be duplicates. To make it simple I did this. Btw thanks for your contribution (upvoted)

@克里斯,我也同意你的评论。我们应该使用动态值,而不是索引,因为可能存在重复项。为了简单起见,我这么做了。顺便说一句,感谢您的贡献(已获得好评)

was looking for this same answer even I had a component like this and was frustated

我正在寻找同样的答案,即使我有一个这样的组件,并得到了成果

This is not entirely correct. Rendering will not be faster if you add the key prop. If you don't provide one, React will assign one automatically (the current index of the iteration).

这并不完全正确。如果添加关键道具,渲染速度将不会更快。如果您没有提供索引,Reaction将自动分配一个索引(迭代的当前索引)。

@Chris in that case why it raise a warning ?

@Chris在这种情况下,它为什么会发出警告?

because by not providing a key, React doesn't know how your data is modelled. This can lead to undesired results if the array is modified.

因为由于不提供密钥,Reaction不知道您的数据是如何建模的。如果数组被修改,这可能会导致不需要的结果。

@Chris in that case of array modification, will React correct the indices according to that if we did not provide keys. Anyway I thought removing extra overhead from React will make some impact on the rendering process.

@Chris在数组修改的情况下,如果我们没有提供键,会根据这一点来反应更正索引。无论如何,我认为从Reaction中删除额外的开销会对渲染过程产生一些影响。

again, React will basically do key={i}. So it depends on the data your array contains. For example, if you have the list ["Volvo", "Tesla"], then obviously the Volvo is identified by the key 0 and the Tesla with 1 - because that is the order they will appear in the loop. Now if you reorder the array the keys are swapped. For React, since "object" 0 is still at the top, it will rather interpret this change as a "rename", rather than a reorder. The correct keys here would need to be, in order, 1 then 0. You don't always reorder mid runtime, but when you do, it's a risk.

同样,Reaction基本上会做key={i}。因此,这取决于数组包含的数据。例如,如果你有列表[“Volvo”,“Tesla”],那么很明显,沃尔沃用键0来标识,而特斯拉用1来标识-因为这是它们在循环中出现的顺序。现在,如果您对数组重新排序,则会交换密钥。对于Reaction,由于“Object”0仍然位于首位,它更愿意将此更改解释为“重命名”,而不是重新排序。这里的正确密钥需要按从1到0的顺序。您并不总是在运行时中期重新排序,但当您这样做时,这是有风险的。

With every render cycle, you are calling the randomizer to assign a new key to each li, forcing them to re-render. This is highly inefficient. Rather, you should ensure that the assigned ID does not change if the list item does not change.

在每个渲染周期中,调用随机生成器为每个li指定一个新关键点,强制它们重新渲染。这是非常低效的。相反,如果列表项没有更改,则应确保分配的ID不会更改。

I may be incorrect but the key needs to be on the highest element that's iterated over, so if you're including the fragments they'd need to be changed to <React.Fragment key={index}><React.Fragment />. Sadly you can't include a key in an empty fragment. But I don't think they're necessary as there's only one parent element inside the map

我可能是不正确的,但键需要位于迭代过的最高元素上,因此,如果包括片段,则需要将它们更改为。遗憾的是,您不能在空片段中包含密钥。但我不认为它们是必要的,因为映射中只有一个父元素

` rowKey={(item) => item.id}` attribute inside the table tag solved my issue

表标签内的`rowKey={(Item)=>item.id}`属性解决了我的问题

This is most likely an issue with browser cache. You can hard-refresh on the same local host to remove any stored cache.

这很可能是浏览器缓存的问题。您可以在同一本地主机上硬刷新以删除任何存储的缓存。

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com