【问题标题】:Warning: flattenChildren(...): Encountered two children with the same key警告:flattenChildren(...):遇到两个孩子用相同的键
【发布时间】:2017-05-17 06:58:43
【问题描述】:

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

当我将 ToDo 检查为 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)

谢谢,抱歉英语不好!

【问题讨论】:

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


    【解决方案1】:

    问题在于您的reducer。您无需找到要完成的待办事项并将其完成值编辑为真,而是将所述待办事项的副本附加到数组的末尾。这会使您的应用尝试呈现所有待办事项,即使存在具有相同 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
          }
        )
    }
    

    现在您可以像这样修改减速器中的状态:

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

    这应该可以解决问题。我还建议至少在你的 reducer 中使用 Immutable.js。很多时候它会使编辑你的状态变得更简单。当然,这又取决于你。

    【讨论】:

    • 谢谢!我认为我仍然对 Redux 的工作方式感到困惑 =)
    • 好吧,每当一个动作被触发,你编辑你的状态并返回它。我想你确实理解那部分。您刚刚错误地编辑了您的状态。您不必使用数组解构本身([...state, {}] 部分)。只要避免副作用,您就可以随意编写它。
    猜你喜欢
    • 2017-12-15
    • 2016-01-28
    • 2016-07-10
    • 2017-09-11
    • 1970-01-01
    • 2017-08-08
    • 2018-01-01
    • 2017-06-01
    • 1970-01-01
    相关资源
    最近更新 更多