1

わかりました、学習目的で単純な 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;
    }
}

残りのコードはこちら (GitHub)

ありがとう、悪い英語でごめんなさい!

4

1 に答える 1

2

問題はreducerにあります。完了したい todo を見つけてその completed-value を true に編集する代わりに、その todo のコピーを配列の末尾に追加します。これにより、同じ ID (および同じキー) を持つエントリが複数ある場合でも、アプリはすべての todo をレンダリングしようとします。
これを行っています:
初期状態: [todo1: completed, todo2: not completed, todo3: completed]
最終状態: [todo:1 completed, todo2: not completed, todo3: completed, todo2: completed]
ただし、これは私たちが望んでいるものではありません。

Todo をループして、完了したいものを見つけて変更することで、問題を解決しました。
この関数をレデューサーと同じファイルに追加しました (もちろん、適切と思われる方法で実装できます)。

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)

これでうまくいくはずです。また、少なくともレデューサーでは Immutable.js を使用することをお勧めします。多くの場合、状態の編集がより簡単になります。もちろん、それはあなた次第です。

于 2017-01-03T09:01:10.580 に答える