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

React Native集成Zustand Persist实现Todo应用报错求助

React Native + Zustand Persist Todo应用问题解决

问题回顾

尝试用React Native和Zustand Persist实现简易Todo应用,未使用persist时运行正常,引入后添加Todo时报错:

ERROR  TypeError: Invalid attempt to spread non-iterable instance.
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.

日志显示,使用persist后state.todos变成嵌套对象而非数组,导致展开操作失败。

错误原因

  1. 手动读取本地存储多余且冲突:Zustand的persist中间件会自动完成数据持久化和加载(hydration),自定义的getTodos方法手动读取AsyncStorage并设置state,破坏了persist管理的state结构,让todos变成嵌套对象。
  2. 拼写错误:AsynStorage应为AsyncStorage,少写字母c可能导致存储读写失败。
  3. 类型处理不当:用@ts-ignore规避类型错误,不如通过正确类型定义解决。

修正后的代码

Zustand Store(完整代码)

import create from 'zustand';
import { persist, PersistOptions } from 'zustand/middleware';
import AsyncStorage from '@react-native-async-storage/async-storage';

export interface Todo {
  id: string;
  text: string;
  completed: boolean;
  createdAt: string;
}

export interface TodoState {
  todos: Todo[];
  addTodo: (todo: Todo) => void;
  removeTodo: (id: string) => void;
  toggleTodo: (id: string) => void;
}

// 定义持久化配置类型,避免类型报错
type TodoPersistConfig = PersistOptions<TodoState, Partial<TodoState>>;

export const useTodoStore = create<TodoState>(
  persist(
    (set) => ({
      todos: [],
      addTodo: (todo: Todo) => {
        set((state) => ({
          ...state,
          todos: [...state.todos, todo],
        }));
      },
      removeTodo: (id: string) => {
        set((state) => ({
          ...state,
          todos: state.todos.filter((todo) => todo.id !== id),
        }));
      },
      toggleTodo: (id: string) => {
        set((state) => ({
          ...state,
          todos: state.todos.map((todo) =>
            todo.id === id ? { ...todo, completed: !todo.completed } : todo
          ),
        }));
      },
    }),
    {
      name: 'todo-storage',
      getStorage: () => AsyncStorage,
    } as TodoPersistConfig
  )
);

App.tsx(修改后)

const App = () => {
  const { todos, addTodo } = useTodoStore((state: TodoState) => state);

  // 无需手动调用getTodos,persist中间件会自动加载本地存储的数据

  return (
    // 你的UI组件
    ...
  )
}

关键说明

  • 移除多余的getTodos方法,让persist中间件自动处理数据加载,保证state.todos始终是数组类型。
  • 修正AsyncStorage拼写错误,确保存储功能正常。
  • 通过定义TodoPersistConfig类型替换@ts-ignore,解决类型报错问题。
  • 现在添加Todo时,state.todos是正常数组,展开操作不会再报错,数据也会自动持久化到本地存储。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 15:39:37