Zustand多Store重置异常:页面重载后状态未正确重置
问题描述
我创建了多个Zustand Store,可正常运行。点击登出时调用resetAllStores将Store设为默认值,此时localStorage中可见默认值;但再次登录并重载页面后,initialState会带上API返回的已设置值,再次点击登出无法将Store重置为默认值。
具体场景:
- 登录时设置user为
{name: 'TEST NAME'} - 登出后设为
{user: null},localStorage显示正常 - 重载页面后user又变回
{name: 'TEST NAME'} - 尝试过相关指南但对页面重载无效
附带相关代码:
import { StoreApi, UseBoundStore, create } from 'zustand'; import { devtools, persist } from 'zustand/middleware'; export type Store<T extends unknown> = UseBoundStore<StoreApi<T>>; const storeResetFns = new Set<() => void>(); export const resetAllStores = () => { storeResetFns.forEach(resetFn => { resetFn(); }); }; export const createStore = <T extends unknown>( fn: (set: StoreApi<T>['setState'], get: StoreApi<T>['getState'], api: StoreApi<T>) => T, persistName: string, devToolsName?: string ): Store<T> => { const store = create<T>()( devtools(persist(fn, { name: persistName }), { name: devToolsName || persistName, enabled: process.env.NODE_ENV === 'development', }) ); const initialState = store.getState(); storeResetFns.add(() => { store.setState(initialState, true); }); return store; }; const initialState = { user: null } export const useAuth = createStore<AuthState & AuthActions>( immer(set => ({ ...initialState, })), 'auth' );
问题原因
核心问题出在createStore函数中:你通过store.getState()获取initialState,但因为使用了persist中间件,页面重载时Store会从localStorage恢复之前保存的登录状态,此时initialState就变成了登录后的用户数据,而非你定义的原始默认值{user: null}。后续调用重置函数时,实际是把Store设为了这个“被污染”的初始值,导致登出后重载页面又恢复了旧数据。
解决方法
方法一:传入原始初始状态(最稳妥)
修改createStore,让它接收原始的初始状态参数,确保重置时始终使用真正的默认值:
import { StoreApi, UseBoundStore, create } from 'zustand'; import { devtools, persist } from 'zustand/middleware'; export type Store<T extends unknown> = UseBoundStore<StoreApi<T>>; const storeResetFns = new Set<() => void>(); export const resetAllStores = () => { storeResetFns.forEach(resetFn => { resetFn(); }); }; // 新增initialState参数,接收原始默认值 export const createStore = <T extends unknown>( fn: (set: StoreApi<T>['setState'], get: StoreApi<T>['getState'], api: StoreApi<T>) => T, persistName: string, initialState: T, devToolsName?: string ): Store<T> => { const store = create<T>()( devtools(persist(fn, { name: persistName }), { name: devToolsName || persistName, enabled: process.env.NODE_ENV === 'development', }) ); // 用传入的原始初始状态重置 storeResetFns.add(() => { store.setState(initialState, true); }); return store; }; const initialState = { user: null } // 创建store时传入原始初始状态 export const useAuth = createStore<AuthState & AuthActions>( immer(set => ({ ...initialState, })), 'auth', initialState, );
方法二:利用persist中间件自带的reset方法
Zustand的persist中间件自带reset方法,可直接清除持久化存储并重置到初始状态:
import { StoreApi, UseBoundStore, create } from 'zustand'; import { devtools, persist } from 'zustand/middleware'; export type Store<T extends unknown> = UseBoundStore<StoreApi<T>>; const storeResetFns = new Set<() => void>(); export const resetAllStores = () => { storeResetFns.forEach(resetFn => { resetFn(); }); }; export const createStore = <T extends unknown>( fn: (set: StoreApi<T>['setState'], get: StoreApi<T>['getState'], api: StoreApi<T>) => T, persistName: string, devToolsName?: string ): Store<T> => { const store = create<T>()( devtools(persist(fn, { name: persistName }), { name: devToolsName || persistName, enabled: process.env.NODE_ENV === 'development', }) ); // 获取persist的reset方法 const persistReset = (store as any).persist?.reset; if (persistReset) { storeResetFns.add(persistReset); } else { // 兼容非持久化Store,用初始状态重置 const initialState = store.getState(); storeResetFns.add(() => store.setState(initialState, true)); } return store; }; const initialState = { user: null } export const useAuth = createStore<AuthState & AuthActions>( immer(set => ({ ...initialState, })), 'auth' );
方法三:手动清除localStorage并重置
重置时不仅设置状态为初始值,还要手动清除对应localStorage项:
import { StoreApi, UseBoundStore, create } from 'zustand'; import { devtools, persist } from 'zustand/middleware'; export type Store<T extends unknown> = UseBoundStore<StoreApi<T>>; const storeResetFns = new Set<() => void>(); export const resetAllStores = () => { storeResetFns.forEach(resetFn => { resetFn(); }); }; export const createStore = <T extends unknown>( fn: (set: StoreApi<T>['setState'], get: StoreApi<T>['getState'], api: StoreApi<T>) => T, persistName: string, devToolsName?: string ): Store<T> => { const store = create<T>()( devtools(persist(fn, { name: persistName }), { name: devToolsName || persistName, enabled: process.env.NODE_ENV === 'development', }) ); const initialState = store.getState(); storeResetFns.add(() => { store.setState(initialState, true); // 清除对应localStorage项 localStorage.removeItem(persistName); }); return store; }; const initialState = { user: null } export const useAuth = createStore<AuthState & AuthActions>( immer(set => ({ ...initialState, })), 'auth' );
内容的提问来源于stack exchange,提问作者Vadim Diachenko
相关产品推荐
相关产品推荐

