React js:警告:列表中的每个子项都应该有一个唯一的“键”道具

React js: Warning: Each child in a list should have a unique "key" prop

提问人:Sameer 提问时间:8/30/2023 最后编辑:Sameer 更新时间:8/30/2023 访问量:62

问:

我知道这是最常见的问题,但我在这里, 我正在创建 todo react 应用程序,我刚刚开始使用 react,但问题是我已经传递了 然后用作组件中的关键道具,idTodo

我尝试了一些解决方案,但这次我无法理解,即使我传递了 then using 作为 then 为什么会发生此错误idkey

import React from "react";
import Todo from "./todo";
const taskList = ({ items }) => {
    let itemsDisplay = [];

    if (items.length > 0) {

        itemsDisplay = items.map((todo, i) => {
            return <Todo id={i} todo={todo} />
        });
    }
    return (
        <>
            {itemsDisplay}
        </>
    )

}


export default taskList; 

这是我的任务列表,它将接收任务列表,这些任务是对象数组

这是我的待办事项组件


import React from "react";
import './todo.css'
const Todo = ({ id, todo }) => {
    console.log(id, todo);
    return (
        <div style={{ display: "flex" }}>
            <li
                style={{
                    cursor: "pointer",
                    marginRight: "1rem"
                }}
                key={id}
                className={todo.complete ? "strike" : ""} >
                {todo.task}
            </li>

            <button  >
                Edit
            </button>
            <button >
                Delete buttn
            </button>
        </div>
    )
}

export default Todo;
JavaScript ReactJS 对象 react-hooks

评论

0赞 Emilien 8/30/2023
将 key 属性移动到 Todo 元素。 并将其从<li中删除>return <Todo key={i} todo={todo} />

答:

4赞 Imran Rafiq Rather 8/30/2023 #1

你必须提供来自 React 的属性,而不是一个属性:keyid

 itemsDisplay = items.map((todo, i) => {
        return <Todo key={i} todo={todo} />
    });

快速提示:始终在迭代时(在迭代时)提供密钥,在这种情况下,您正在使用函数进行迭代,因此这有助于避免混淆。map()

从子 Todo 来看,它在这种情况下不起作用。React 就是这样工作的。

评论

1赞 Sameer 8/30/2023
我以为我们只能传递给 JSX 标签,我不知道这个谢谢伙计key
0赞 Imran Rafiq Rather 8/30/2023
我的请伙计。我们也可以在迭代或映射时放入组件。(一般规则,避免混淆兄弟)
0赞 Imran Rafiq Rather 8/30/2023
stackoverflow.com/help/someone-answers@Sameer
1赞 Sameer 8/30/2023
我会记住这一点,谢谢伙计
1赞 Conner 8/30/2023 #2

你必须把你放在'div'上,所以你的待办事项组件应该看起来像这样:key={id}

import React from "react";
import './todo.css'
const Todo = ({ id, todo }) => {
    console.log(id, todo);
    return (
        <div style={{ display: "flex" }} key={id}>
            <li
                style={{
                    cursor: "pointer",
                    marginRight: "1rem"
                }}
                className={todo.complete ? "strike" : ""} >
                {todo.task}
            </li>

            <button  >
                Edit
            </button>
            <button >
                Delete buttn
            </button>
        </div>
    )
}

export default Todo;

React 使用 key prop 在组件和 DOM 元素之间创建关系。该库使用此关系来确定是否应重新呈现组件。

评论

0赞 Sameer 8/30/2023
不,伙计,这行不通,我已经通过给 div 的密钥尝试过了,但它仍然显示错误,就像我提到的顺便说一句,谢谢
1赞 Andy 8/30/2023 #3
  1. 您的组件名称应在 PascalCase 中。我还建议给它起个名字,因为它正在构建一个待办事项列表,并且一致性对于调试很有用。Todos

  2. 无需在组件中创建空数组。据推测,您在组件中传递的数据是一个数组,因此您需要做的就是检查该数组是否为空。如果它是返回一些东西以显示没有数据 - 否则用于遍历数组。map

  3. 重新提出问题:该属性应地图迭代过程中添加。它不是需要传递给组件的东西。例如,如果你选择对列表重新排序,这只是 React 更好地协调更改的一种方式。key

  4. 在最后一点上,不应将索引用于键值。希望您的待办事项每个都有一个 id。如果他们不考虑添加一个。然后,您可以将其用作键,也可以用作在添加该代码时可以完成/删除待办事项的机制。map

const { useState } = React;

function Todos({ todos }) {

  if (!todos.length) return <div>Empty</div>;

  return (
    <section>
      {todos.map(todo => {
        return <Todo key={todo.id} todo={todo} />
      })}
    </section>
  );

}

function Todo({ todo }) {
  return (
    <div style={{ display: "flex" }}>
      <li
        style={{
          cursor: "pointer",
          marginRight: "1rem"
        }}
        className={todo.complete ? "strike" : ""}
      >{todo.task}
      </li>
      <button>Edit</button>
      <button>Delete</button>
    </div>
  );
}

const todos = [
  { id: 1, task: 'Write task 1', complete: false },
  { id: 2, task: 'Write task 2', complete: false },
  { id: 3, task: 'Write task 3', complete: false }
];

const node = document.getElementById('root');
const root = ReactDOM.createRoot(node);
root.render(<Todos todos={todos} />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script>
<div id="root"></div>

评论

0赞 Sameer 8/30/2023
Hy mate thanks for the useful suggestions this is my Todolist component' import React from “react”;从 “./todo” 导入 Todo;const Tasklist = ({ items }) => { return ( <> {items.map((todo, i) => { return <Todo key={i} todo={todo} /> })} </> ) } export default Tasklist;' 对于检查,我已经在我的应用程序组件中执行此操作,因此该组件中的检查是不需要的,最后是关于我计划将 ID 分配为变量的 ID 的事情
0赞 Sameer 9/19/2023
所以基本上你说的是,当我们迭代某件事时,我们需要将密钥传递给 elemet,例如,这里有 div,然后在它里面,所以我不会传递给 li,而是我会在 div 上设置密钥,因为,我正在制作的列表或遍历列表li
0赞 Andy 9/19/2023
@Sameer。这要视情况而定。在每次迭代中,我们都使用一个组件,所以关键在于此。TodosTodo