警告:flattenChildren(...):遇到两个孩子用同一把钥匙

时间:2017-01-03 08:23:44

标签: reactjs ecmascript-6 key redux create-react-app

好的,我正在构建一个简单的ToDo应用程序用于学习目的,我面临一个我无法解决的警告:

当我检查ToDo as Done时,会抛出错误。我试图将密钥设置为每个元素的索引,警告停止,但是当列表更新时,会呈现重复的元素。

继承我的组成部分:

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)

谢谢,对不好的英语感到抱歉!

1 个答案:

答案 0 :(得分:2)

问题在于 reducer 。您没有找到要完成的待办事项并将其完成值编辑为真,而是将所述待办事项的副本附加到数组的末尾。这使得您的应用尝试渲染所有待办事项,即使有相同ID(和相同键)的条目。
你是这样做的:
初始状态: [todo1: completed, todo2: not completed, todo3: completed]
最终状态: [todo:1 completed, todo2: not completed, todo3: completed, todo2: completed]
然而,这不是我们想要的。

我通过循环你的待办事项,找到你要完成的那个并修改那个来解决你的问题 我在与reducer相同的文件中添加了这个函数(当然,你可以实现它,但你认为合适)。

function completeTodo(todos, id) {
  return todos
    .map(
      todo => {
        if (todo.id === id)
          todo.isCompleted = true
        return todo
      }
    )
}

现在您可以在减速器中修改状态,如下所示:

   case "CHECK_TODO":
            return completeTodo(state, action.payload.id)

这应该可以解决问题。我还建议至少在reducers中使用Immutable.js。它可以在很多时候简化编辑你的状态。但是,当然,这再次取决于你。