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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 17:06:00