警告:flattenChildren(...):遇到两个 children 具有相同的键
Warning: flattenChildren(...): Encountered two children with the same key
好的,我正在构建一个简单的 ToDo 应用程序用于学习目的,我面临着一个我无法解决的警告:
当我将 ToDo 检查为完成时,抛出错误。我尝试将键设置为每个元素的索引,警告停止了,但是列表更新时呈现了重复的元素。
这是我的组件:
import React from "react";
import TodoTask from "./TodoTask";
const TodoList = ({todos, onTaskCheck}) => {
function renderList() {
return (
todos.map((todo) => {
return <TodoTask key={todo.id} todo={todo} onTaskCheck={onTaskCheck} />
})
);
}
return (
<div>
<h1 className="title is-4">ToDo List</h1>
<ul className="task-list">
{renderList()}
</ul>
</div>
);
};
export default TodoList;
这是减速器:
export default function TodoReducers(state = [], action) {
switch(action.type) {
case "LIST_TODOS":
return [
{id: 1, description: "Task 1", isCompleted: true},
{id: 2, description: "Task 2", isCompleted: true},
{id: 3, description: "Task 3", isCompleted: true},
{id: 4, description: "Task 4", isCompleted: false},
{id: 5, description: "Task 5", isCompleted: false}
];
case "CHECK_TODO":
return [...state, Object.assign({}, action.payload, action.payload.isCompleted = true)];
default:
return state;
}
}
The rest of the code is here (GitHub)
谢谢,抱歉英语不好!
问题出在你的reducer。您不是找到要完成的待办事项并将其完成的值编辑为 true,而是将所述待办事项的副本附加到数组的末尾。这会使您的应用尝试呈现所有待办事项,即使存在具有相同 ID(和相同键)的条目。
您正在这样做:
初始状态:[todo1: completed, todo2: not completed, todo3: completed]
最终状态: [todo:1 completed, todo2: not completed, todo3: completed, todo2: completed]
但这不是我们想要的。
我通过遍历你的待办事项解决了你的问题,找到你想要完成的并修改那个。
我将此功能添加到与您的减速器相同的文件中(当然,您可以根据需要实现它)。
function completeTodo(todos, id) {
return todos
.map(
todo => {
if (todo.id === id)
todo.isCompleted = true
return todo
}
)
}
现在您可以像这样在 reducer 中修改状态:
case "CHECK_TODO":
return completeTodo(state, action.payload.id)
这应该可以解决问题。我还建议至少在你的减速器中使用 Immutable.js 。很多时候,它会使编辑状态变得更简单。当然,这又取决于你。
好的,我正在构建一个简单的 ToDo 应用程序用于学习目的,我面临着一个我无法解决的警告:
当我将 ToDo 检查为完成时,抛出错误。我尝试将键设置为每个元素的索引,警告停止了,但是列表更新时呈现了重复的元素。
这是我的组件:
import React from "react";
import TodoTask from "./TodoTask";
const TodoList = ({todos, onTaskCheck}) => {
function renderList() {
return (
todos.map((todo) => {
return <TodoTask key={todo.id} todo={todo} onTaskCheck={onTaskCheck} />
})
);
}
return (
<div>
<h1 className="title is-4">ToDo List</h1>
<ul className="task-list">
{renderList()}
</ul>
</div>
);
};
export default TodoList;
这是减速器:
export default function TodoReducers(state = [], action) {
switch(action.type) {
case "LIST_TODOS":
return [
{id: 1, description: "Task 1", isCompleted: true},
{id: 2, description: "Task 2", isCompleted: true},
{id: 3, description: "Task 3", isCompleted: true},
{id: 4, description: "Task 4", isCompleted: false},
{id: 5, description: "Task 5", isCompleted: false}
];
case "CHECK_TODO":
return [...state, Object.assign({}, action.payload, action.payload.isCompleted = true)];
default:
return state;
}
}
The rest of the code is here (GitHub)
谢谢,抱歉英语不好!
问题出在你的reducer。您不是找到要完成的待办事项并将其完成的值编辑为 true,而是将所述待办事项的副本附加到数组的末尾。这会使您的应用尝试呈现所有待办事项,即使存在具有相同 ID(和相同键)的条目。
您正在这样做:
初始状态:[todo1: completed, todo2: not completed, todo3: completed]
最终状态: [todo:1 completed, todo2: not completed, todo3: completed, todo2: completed]
但这不是我们想要的。
我通过遍历你的待办事项解决了你的问题,找到你想要完成的并修改那个。
我将此功能添加到与您的减速器相同的文件中(当然,您可以根据需要实现它)。
function completeTodo(todos, id) {
return todos
.map(
todo => {
if (todo.id === id)
todo.isCompleted = true
return todo
}
)
}
现在您可以像这样在 reducer 中修改状态:
case "CHECK_TODO":
return completeTodo(state, action.payload.id)
这应该可以解决问题。我还建议至少在你的减速器中使用 Immutable.js 。很多时候,它会使编辑状态变得更简单。当然,这又取决于你。