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

React中如何在Reducer将已有项添加到新状态?Todo应用开发问题

实现待办任务从Pending到Completed的状态转移

核心思路:在Reducer中新增MARK_COMPLETED动作

既然已经用useReducer管理状态,最直接的方式就是在现有Reducer中添加处理任务完成的逻辑,步骤如下:


1. 定义新的Action类型

可以单独定义常量,也可以直接在代码里使用字符串:

const MARK_COMPLETED = 'MARK_COMPLETED';

2. 改造Reducer,添加MARK_COMPLETED的处理逻辑

假设你的初始状态结构是:

const initialState = {
  pending: [], // 待办任务数组,每个任务需包含唯一id,比如{ id: 1, text: '写代码' }
  completed: [], // 已完成任务数组
  // 其他状态字段...
};

修改Reducer函数,新增对应case:

function taskReducer(state, action) {
  switch (action.type) {
    case 'ADD_PENDING':
      // 保留你原有的添加待办逻辑
      return {
        ...state,
        pending: [...state.pending, action.payload],
      };
    case MARK_COMPLETED: {
      // 定位要转移的目标任务
      const targetTask = state.pending.find(task => task.id === action.payload.taskId);
      if (!targetTask) return state; // 未找到任务则直接返回原状态

      // 不可变更新状态:从pending移除任务,同时添加到completed
      return {
        ...state,
        pending: state.pending.filter(task => task.id !== action.payload.taskId),
        completed: [...state.completed, targetTask],
      };
    }
    default:
      return state;
  }
}

3. 在Pending组件中绑定完成按钮的dispatch逻辑

将dispatch方法通过props传递给Pending组件,给完成按钮绑定点击事件:

// Pending组件示例
function Pending({ pendingTasks, dispatch }) {
  return (
    <div>
      <h2>待办任务</h2>
      {pendingTasks.map(task => (
        <div key={task.id}>
          <span>{task.text}</span>
          <button
            onClick={() => {
              dispatch({
                type: MARK_COMPLETED,
                payload: { taskId: task.id },
              });
            }}
          >
            标记完成
          </button>
        </div>
      ))}
    </div>
  );
}

其他可行方案

如果不想基于Reducer扩展,也可以用useState直接处理:在父组件中定义状态更新函数,传递给Pending组件调用。示例如下:

// 父组件中用useState的实现
const [pending, setPending] = useState([]);
const [completed, setCompleted] = useState([]);

const handleMarkCompleted = (taskId) => {
  const targetTask = pending.find(t => t.id === taskId);
  if (!targetTask) return;
  // 不可变更新两个数组
  setPending(prev => prev.filter(t => t.id !== taskId));
  setCompleted(prev => [...prev, targetTask]);
};

之后将handleMarkCompleted作为props传给Pending组件,按钮点击时调用该函数即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 08:54:17