Zustand persist中间件致GlobalStoreSlice方法丢失问题求助
问题:Zustand组合persist封装的Slice后方法显示为Null
问题描述
在React应用中使用Zustand创建了两个带persist中间件的Slice:login.ts中的LoginStoreSlice和global.ts中的GlobalStoreSlice,并在store/index.ts中组合所有Slice。目前遇到的问题是:GlobalStoreSlice中的setColor和todoColor方法显示为Null,但未被persist封装的createFishSlice、createBearSlice内的方法可正常使用。
相关代码
// global.ts import {persist} from "zustand/middleware"; const Storage = { name: "primaryColor", } export const GlobalStoreSlice = persist( (set) => ( { primaryColor: "#247fff", setColor: (color) => set(() => ({primaryColor: color})), todoColor: () => set(() => ({primaryColor: "black"})) } ), Storage ) export const createFishSlice = (set) => ({ fishes: 0, addFish: () => set((state) => ({fishes: state.fishes + 1})), }) export const createBearSlice = (set) => ({ bears: 0, addBear: () => set((state) => ({bears: state.bears + 1})), eatFish: () => set((state) => ({fishes: state.fishes - 1})), })
// login.ts import {persist} from "zustand/middleware"; const Storage = { name: 'userInfo' } export const LoginStoreSlice = persist( (set) => ( { userInfo: null, setUserInfo: (info) => set(() => ({userInfo: info})), } ), Storage )
// store/index.ts import {create} from "zustand"; import {devtools, persist} from "zustand/middleware"; import {LoginStoreSlice} from '@/stores/login' import {GlobalStoreSlice, createBearSlice, createFishSlice} from '@/stores/global' export const UseStore = create( devtools( (...a) => ({ ...LoginStoreSlice(...a), ...GlobalStoreSlice(...a), ...createBearSlice(...a), ...createFishSlice(...a), }) ) )
原因分析
Zustand的persist是高阶中间件,它返回的不是普通Slice函数,而是经过封装的增强函数。当直接在组合对象中展开两个已被persist包裹的Slice时,两个persist实例会互相干扰,破坏对方的方法封装逻辑,最终导致被persist处理后的方法丢失并显示为Null。
解决方法
方案1:全局统一持久化(推荐)
将persist作为最外层中间件包裹整个组合后的store,同时移除单个Slice内的persist封装:
- 修改
global.ts和login.ts,去掉内部的persist:
// global.ts 修改后 export const GlobalStoreSlice = (set) => ({ primaryColor: "#247fff", setColor: (color) => set(() => ({primaryColor: color})), todoColor: () => set(() => ({primaryColor: "black"})) }) // login.ts 修改后 export const LoginStoreSlice = (set) => ({ userInfo: null, setUserInfo: (info) => set(() => ({userInfo: info})), })
- 修改
store/index.ts,用persist包裹整个组合store:
import {create} from "zustand"; import {devtools, persist} from "zustand/middleware"; import {LoginStoreSlice} from '@/stores/login' import {GlobalStoreSlice, createBearSlice, createFishSlice} from '@/stores/global' const baseStore = (...a) => ({ ...LoginStoreSlice(...a), ...GlobalStoreSlice(...a), ...createBearSlice(...a), ...createFishSlice(...a), }) export const UseStore = create( devtools( persist(baseStore, { name: 'app-store', // 可选:指定只持久化部分状态 partialize: (state) => ({ userInfo: state.userInfo, primaryColor: state.primaryColor }) }) ) )
方案2:单个Slice独立持久化
如果需要每个Slice使用独立的存储key,可通过combine工具正确组合多个persist封装的Slice:
// store/index.ts 修改后 import {create, combine} from "zustand"; import {devtools, persist} from "zustand/middleware"; import {LoginStoreSlice} from '@/stores/login' import {GlobalStoreSlice, createBearSlice, createFishSlice} from '@/stores/global' export const UseStore = create( devtools( combine( {}, (set, get) => ({ ...persist(LoginStoreSlice, {name: 'userInfo'})(set, get), ...persist(GlobalStoreSlice, {name: 'primaryColor'})(set, get), ...createBearSlice(set), ...createFishSlice(set), }) ) ) )
同时需将global.ts和login.ts中的Slice改为普通函数(移除自身的persist包裹)。
内容的提问来源于stack exchange,提问作者buyowner
相关产品推荐
相关产品推荐

