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

React中使用useReducer时如何从localStorage获取text数据?

问题修复与解答

错误原因分析

  1. Uncaught TypeError: init is not a function:useReducer的第三个参数要求是初始化函数,但你传入的是initialTasks对象,不符合API规范。
  2. localStorage读取后显示空数组:你的tasksReducer处理的是数组类型的状态,但组件中useReducer的初始值设为了{ tasks: [] }(对象类型),状态结构不匹配,导致读取localStorage后无法正确映射到组件状态。

代码修改方案

1. 修改ReducerPractice.js

...
import tasksReducer from "./tasksReducer";

// 定义初始化函数,从localStorage读取任务数组
const getInitialTasks = () => {
  const storedTasks = localStorage.getItem("tasks");
  return storedTasks ? JSON.parse(storedTasks) : [];
};

export default function ReducerPrac() {
  // 状态直接为任务数组,与reducer处理的结构保持一致
  const [tasks, dispatch] = useReducer(
    tasksReducer,
    [],
    getInitialTasks // 传入初始化函数
  );

  const tasksId = useRef(0);
  function handleAddTask(text) {
    tasksId.current += 1; // 修正id递增逻辑,避免重复
    dispatch({
      type: "added",
      id: tasksId.current,
      text: text,
    });
  }

  function handleChangeTask(updatedTask) {
    dispatch({
      type: "changed",
      task: updatedTask, // 调整action字段名,逻辑更清晰
    });
  }

  function handleDeleteTask(taskId) {
    dispatch({
      type: "deleted",
      id: taskId,
    });
  }

  useEffect(() => {
    localStorage.setItem("tasks", JSON.stringify(tasks));
  }, [tasks]);

  return (
    <>
      <h3>Reducer todo</h3>
      <AddTask onAddTask={handleAddTask} />
      <br />
      <TaskList
        tasks={tasks}
        onChangeTask={handleChangeTask}
        onDeleteTask={handleDeleteTask}
      />
    </>
  );
}

2. 修改tasksReducer.js

export default function tasksReducer(tasks, action) {
  switch (action.type) {
    case "added": {
      return [
        ...tasks,
        { id: action.id, text: action.text, done: false },
      ];
    }
    case "changed": {
      // 对应修改后的action字段,用action.task获取更新后的任务
      return tasks.map((t) => {
        if (t.id === action.task.id) {
          return action.task;
        } else {
          return t;
        }
      });
    }
    case "deleted": {
      return tasks.filter((t) => t.id !== action.id);
    }
    default: {
      throw new Error("Unknown dispatched action: " + action.type);
    }
  }
}

关于useContext的问题

在React中结合useReducer和localStorage时,不是必须搭配useContext:

  • 如果只有单个组件或少数几层子组件需要访问任务状态和dispatch方法,直接通过props传递即可。
  • 当多个不相关的组件(跨多层组件树)需要共享状态和dispatch时,才需要用useContext封装reducer的状态和方法,避免props层层传递的繁琐。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 00:53:22