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

如何在Redux Toolkit中更新嵌套对象?以Todo列表的Steps属性操作为例

How to Update Nested Step Properties in Redux Toolkit

First off, let's clear up your misunderstanding: Redux Toolkit absolutely lets you pass multiple values in an action.payload—you just need to wrap them in an object. You don't have to pass an entire Todo object every time you need to update a nested step. That's the key to cleaning up your code here.

The Optimal Approach: Use Immer's Mutable Syntax for Nested Updates

Redux Toolkit uses Immer under the hood, which lets you write "mutating" code that gets converted into immutable state updates automatically. This is perfect for updating nested properties like your steps—no need to copy entire Todo objects.

1. Add a Reducer for Toggling Step Completion

In your todoSlice.tsx, add a new case to your createSlice definition that targets the specific todo and step directly:

import { createSlice, PayloadAction } from '@reduxjs/toolkit';
// Import your Todo/Step types here

const todoSlice = createSlice({
  name: 'todo',
  initialState: { /* your initial state here */ },
  reducers: {
    // ... your existing reducers (updateTodo, etc.)
    toggleStep: (state, action: PayloadAction<{ todoId: number; stepId: number }>) => {
      const { todoId, stepId } = action.payload;
      // Find the target todo
      const targetTodo = state.todos.find(todo => todo.id === todoId);
      if (targetTodo?.steps) {
        // Find the target step within that todo
        const targetStep = targetTodo.steps.find(step => step.id === stepId);
        if (targetStep) {
          // Immer handles the immutable update behind the scenes
          targetStep.completed = !targetStep.completed;
        }
      }
    },
  },
});

export const { toggleStep, /* other exports */ } = todoSlice.actions;
export default todoSlice.reducer;

2. Call the Reducer in Your Component

Now in your component, you can dispatch this action with just the IDs you need—no need to create a new Todo object:

const Rightbar: React.FC<rightbarProps> = ({ currentTodoId }) => {
  const dispatch = useDispatch();
  const currentTodo = useSelector((state: RootState) => 
    state.todo.todos.find(todo => todo.id === currentTodoId)
  );

  const toggleStepCompletion = (stepId: number) => {
    if (currentTodoId) {
      dispatch(toggleStep({ todoId: currentTodoId, stepId }));
    }
  };

  // ... rest of your component code
};

For General Step Updates (e.g., Editing Title)

If you need to update other properties of a step (like its title), you can create a flexible reducer that accepts partial updates:

updateStep: (state, action: PayloadAction<{
  todoId: number;
  stepId: number;
  updates: Partial<Step>; // Partial lets you pass any subset of Step properties
}>) => {
  const { todoId, stepId, updates } = action.payload;
  const targetTodo = state.todos.find(todo => todo.id === todoId);
  if (targetTodo?.steps) {
    const targetStep = targetTodo.steps.find(step => step.id === stepId);
    if (targetStep) {
      // Merge the updates into the step object
      Object.assign(targetStep, updates);
    }
  }
}

Then use it in your component like this:

const updateStepTitle = (stepId: number, newTitle: string) => {
  if (currentTodoId) {
    dispatch(updateStep({
      todoId: currentTodoId,
      stepId,
      updates: { title: newTitle }
    }));
  }
};

Why This Is Better Than Your Original Approach

  • More efficient: You're only updating the specific step property you need, not replacing the entire Todo object. This reduces unnecessary re-renders and keeps state changes focused.
  • Cleaner code: No need to manually copy the Todo and Steps arrays—Immer handles the immutable updates for you.
  • Semantic actions: Your actions now clearly communicate what's being updated (e.g., toggleStep instead of a generic updateTodo that could mean anything).

Quick Note on Action Payloads

There's no rule that says action.payload has to be a single object or value. Using an object with named properties (like todoId and stepId) makes your code more readable and maintainable than passing multiple separate arguments.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 09:23:14