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

使用next-redux-wrapper时,如何在非组件中调用Redux dispatch?

问题

我用next-redux-wrapper封装了React-Redux store,想在React组件外部(比如axios工具文件)调用dispatch方法,但受限于wrapper的机制无法实现。请问有没有办法在使用wrapper的同时,导入store并调用dispatch?

相关store代码:

import { combineReducers, configureStore } from '@reduxjs/toolkit';
import { persistReducer, persistStore } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import createSagaMiddleware from 'redux-saga';
import authSlice from './slices/authSlice';
import rootSaga from './sagas';

export const rootReducer = combineReducers({
    [authSlice.name]: authSlice.reducer
});
const sagaMiddleware = createSagaMiddleware();

const makeConfiguredStore = () => {
   const store = configureStore({
   reducer: rootReducer,
   middleware: [sagaMiddleware],
   devTools: true,
 });
 sagaMiddleware.run(rootSaga);
 return store;
};

export const makeStore = () => {
  const persistConfig = {
    key: 'nextjs',
    whitelist: ['auth'],
    storage,
  };

  const persistedReducer = persistReducer(persistConfig, rootReducer);

  const store: any = configureStore({
    reducer: persistedReducer,
    middleware: [sagaMiddleware],
    devTools: process.env.NODE_ENV !== 'production',
  });

  sagaMiddleware.run(rootSaga);
  store.__persistor = persistStore(store); // Nasty hack
  return store;
}

export const wrapper = createWrapper<AppStore>(makeStore);

export type AppStore = ReturnType<typeof makeStore>;
export type AppState = ReturnType<AppStore['getState']>;

我在axios工具文件中的尝试代码:

const setHeaders = async () => {
  const token = await refreshOrAccessToken();

  if(!token){
    // const store = makeStore(); 直接创建新store没用,不是应用的实例
    store.dispatch(signoutUser(SESSION_EXPIRY_MSG))
    msalInstance.logoutRedirect();
    throw Error(SESSION_EXPIRY_MSG)
  }
  axiosInstance.defaults.headers.common['Authorization'] = `Bearer ${token}`;
};
解决方案

方法1:将客户端store实例保存为全局变量

修改makeStore函数,在创建store后仅在客户端环境将其保存为全局变量,确保组件外的代码能访问到和应用一致的store实例(避免服务器端请求间的状态污染)。

修改后的makeStore代码:

// 新增变量存储客户端store实例
let clientStore: AppStore | null = null;

export const makeStore = () => {
  // 每次创建store时重新生成sagaMiddleware,避免重复启动saga
  const sagaMiddleware = createSagaMiddleware();
  
  const persistConfig = {
    key: 'nextjs',
    whitelist: ['auth'],
    storage,
  };

  const persistedReducer = persistReducer(persistConfig, rootReducer);

  const store: AppStore = configureStore({
    reducer: persistedReducer,
    middleware: [sagaMiddleware],
    devTools: process.env.NODE_ENV !== 'production',
  });

  sagaMiddleware.run(rootSaga);
  store.__persistor = persistStore(store);

  // 仅在客户端环境保存store实例
  if (typeof window !== 'undefined') {
    clientStore = store;
    // 也可挂载到window对象,方便其他文件直接访问
    (window as any).reduxStore = store;
  }

  return store;
}

// 导出获取客户端store的方法
export const getClientStore = () => {
  if (typeof window === 'undefined') {
    throw new Error('getClientStore只能在客户端环境调用');
  }
  if (!clientStore) {
    // 若store未初始化,手动创建(应对_app.tsx之前调用的场景)
    clientStore = makeStore();
  }
  return clientStore;
}

在axios工具文件中使用:

import { getClientStore } from '../path/to/store';

const setHeaders = async () => {
  const token = await refreshOrAccessToken();

  if(!token){
    const store = getClientStore();
    store.dispatch(signoutUser(SESSION_EXPIRY_MSG));
    msalInstance.logoutRedirect();
    throw Error(SESSION_EXPIRY_MSG);
  }
  axiosInstance.defaults.headers.common['Authorization'] = `Bearer ${token}`;
};

注意事项

  • 禁止在服务器端代码(如getServerSideProps、API路由)中使用这个全局store,否则会导致不同请求间的状态污染。服务器端每次请求都会调用makeStore生成新的独立store实例。
  • 原代码中全局创建sagaMiddleware会导致重复启动saga,修改后改为在makeStore内部创建实例,解决该问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 08:05:32