You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Redux中修改对象属性?Redux Todo完成功能reducer问题

Fixing the Complete Todo Reducer in Your Redux App

Got it, let's break down what's going wrong with your current reducer and fix it so it properly toggles the complete status of the correct todo item.

The Problem with Your Current Reducer

Your current code is trying to modify the entire chores object directly, which doesn't work for arrays in Redux—we need to target individual items while keeping state immutability. Also, the return structure is incorrect: you're returning { ...state.chores, chore } instead of a new state object containing the updated chores array.

Correct Approach

We need to:

  1. Iterate over the chores array to find the todo matching the one in your action.
  2. For the matching todo, create a new object with the toggled complete value.
  3. Leave all other todos unchanged.
  4. Return a new state object with the updated chores array.

Updated Code

First, tweak your action creator (optional but aligned with Redux conventions)

Renaming data to payload is a common Redux practice, but we'll keep the core logic intact:

export const completeTodo = (todo) => ({ 
  type: 'COMPLETE_TODO', 
  payload: todo 
})

Now the Fixed Reducer

const initialState = { 
  chores: [{name: 'cleaning', complete: false}] 
};

const todoReducer = (state = initialState, action) => {
  switch(action.type) {
    case 'COMPLETE_TODO':
      // Map over chores to create a new array (avoids mutating original state)
      const updatedChores = state.chores.map(chore => {
        // Check if this is the todo we need to update
        if (chore.name === action.payload.name) {
          // Return a new object with toggled complete status
          return { ...chore, complete: !chore.complete };
        }
        // Return the original chore if it's not the target
        return chore;
      });

      // Return a new state object with the updated chores array
      return { ...state, chores: updatedChores };
    
    // Add other action cases (like ADD_TODO) here
    default:
      return state;
  }
};

Why This Works

  • map() creates a brand new array, so we never mutate the original state (a critical Redux rule).
  • We only modify the specific todo that matches the action's payload, leaving all other todos untouched.
  • We return a new state object preserving existing properties (so your state stays consistent if you add more features later).

Pro Tip: Use Unique IDs for Reliability

If you ever have todos with duplicate names, using a unique id will prevent accidental updates. Here's how to adjust:

// Initial state with unique IDs
const initialState = { 
  chores: [{id: 1, name: 'cleaning', complete: false}] 
};

// Updated action creator (pass just the ID)
export const completeTodo = (todoId) => ({ 
  type: 'COMPLETE_TODO', 
  payload: todoId
});

// Updated reducer case
case 'COMPLETE_TODO':
  const updatedChores = state.chores.map(chore => {
    if (chore.id === action.payload) {
      return { ...chore, complete: !chore.complete };
    }
    return chore;
  });
  return { ...state, chores: updatedChores };

内容的提问来源于stack exchange,提问作者The Walrus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:18:48