Переключить состояние значения ключа объекта в массиве - PullRequest
0 голосов
/ 01 октября 2018

Мне нужно создать редуктор, который переключает состояние «сделано» с использованием идентификатора или индекса задачи.

state = {
    todos: [
      {
        title: "eat rice",
        done: false,
        id: 1
      },
      {
        title: "go fishing",
        done: true,
        id: 2
      },
      {
        title: "drink coffee",
        done: false,
        id: 3
      }
    ]
  }

Я пытался это сделать, но он изменяет состояние, а полезная нагрузка является индексом объекта вмассив.

case "DONE":
      const todos = [...state.todos];
      todos[action.payload].done = !todos[action.payload].done;
      return {
        ...state,
        todos: todos
      };

Ответы [ 3 ]

0 голосов
/ 02 октября 2018

Использование оператора распространения или карты создаст новый массив, но не будет автоматически клонировать содержащиеся объекты, так как JavaScript следует «передача по ссылке».Тебе также придется клонировать объект.Так что, может быть, что-то вроде

case "DONE":
  const todos = state.todos.map((todo, index) => {
    const newTodo = {...todo};
    if (action.payload === index) {
      newTodo.done = !todo.done;
    }
    return newTodo;
  });

  return {
    ...state,
    todos,
  };

Конечно, вы также можете использовать утилиту клонирования или что-то вроде Immutable.js.

0 голосов
/ 02 октября 2018

Нашел ответ.Спасибо за вклад.

case "DONE":
      const newTodos = state.todos.map((todo, index) => {
        if (index === action.payload) {
          const newTodo = { ...todo };
          newTodo.done = !newTodo.done;
          return newTodo;
        }

        return todo;
      });

      return {
        ...state,
        todos: newTodos
      };
0 голосов
/ 01 октября 2018

Вместо этого вы можете использовать функцию map.Функция сгенерирует новый массив, который вы можете использовать для замены todos на.

case "DONE":
  const newTodos = state.todos.map((todo, index) => {
    // Based on your code, I assume action.payload is the index of the todo in the array of todos
    if (index === action.payload) {
      const newTodo = {...todo};
      todo.done = !todo.done;
      return todo;
    }

    return todo;
  });

  return {
    ...state,
    todos: newTodos,
  };

Если вы не хотите перебирать каждый todo, вы можете сделать что-то еще, например использовать slice, чтобы создать копию массива и затем изменить одно значение:

case "DONE":
  const newTodos = todos.slice();
  const updatedTodo = {...newTodos[action.payload]};
  updatedTodo.done = !updatedTodo.done;
  newTodos[action.payload] = updatedTodo;

  return {
    ...state,
    todos: newTodos,
  };
...