React Native中工具函数无法访问Redux Store数据的问题
我来帮你解决这个问题——你遇到的核心问题是直接调用configureStore()拿到的是全新的Store实例,和你App里已经初始化、经过Redux Persist持久化的那个完全不是同一个,所以自然拿不到已保存的令牌数据。下面给你两种可行的解决方案,按推荐程度排序:
方案1:导出已初始化的Store实例(最直接)
这是最简单的解决方式,你需要在创建Store的文件(比如store.js)里,把已经初始化并配置好Redux Persist的Store实例导出,而不是只导出configureStore函数。
1.1 修改store.js
// store.js import { configureStore } from '@reduxjs/toolkit'; import createSagaMiddleware from 'redux-saga'; import { persistStore, persistReducer } from 'redux-persist'; import AsyncStorage from '@react-native-async-storage/async-storage'; import rootReducer from './reducers'; import rootSaga from './sagas'; // Redux Persist配置 const persistConfig = { key: 'root', storage: AsyncStorage, whitelist: ['auth'], // 你要持久化的reducer名称 }; const persistedReducer = persistReducer(persistConfig, rootReducer); const sagaMiddleware = createSagaMiddleware(); // 初始化并导出真实的Store实例 export const store = configureStore({ reducer: persistedReducer, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: false }).concat(sagaMiddleware), }); // 启动Saga sagaMiddleware.run(rootSaga); // 导出Persistor(供App入口使用) export const persistor = persistStore(store);
1.2 在api.js中导入这个Store实例
// api.js import axios from 'axios'; import { store } from './store'; // 导入已初始化的Store实例 export const setHeader = () => { // 直接从真实的Store中获取持久化的auth数据 const { auth } = store.getState(); if (auth?.token) { // 校验令牌过期逻辑 const isTokenExpired = checkTokenExpiry(auth.token); if (!isTokenExpired) { axios.defaults.headers.common['Authorization'] = `Bearer ${auth.token}`; } else { // 令牌过期,触发登出action store.dispatch({ type: 'auth/logout' }); delete axios.defaults.headers.common['Authorization']; } } else { delete axios.defaults.headers.common['Authorization']; } }; // 辅助函数:校验JWT令牌过期 const checkTokenExpiry = (token) => { const decoded = JSON.parse(atob(token.split('.')[1])); return Date.now() >= decoded.exp * 1000; };
这样你就能拿到应用中真实的、经过持久化的Store数据,也能直接调用store.dispatch()触发action。
方案2:使用Axios拦截器结合Store(更优雅)
如果想让请求头的设置更自动化,可以把setHeader的逻辑放到Axios的请求拦截器里,同样导入已初始化的Store实例:
// api.js import axios from 'axios'; import { store } from './store'; // 创建专属Axios实例 const api = axios.create({ baseURL: 'https://your-api-domain.com', }); // 请求拦截器:自动添加/校验令牌 api.interceptors.request.use( (config) => { const { auth } = store.getState(); if (auth?.token && !checkTokenExpiry(auth.token)) { config.headers.Authorization = `Bearer ${auth.token}`; } else { store.dispatch({ type: 'auth/logout' }); delete config.headers.Authorization; } return config; }, (error) => Promise.reject(error) ); // 响应拦截器:处理令牌过期后的自动刷新(可选) api.interceptors.response.use( (response) => response, async (error) => { const originalRequest = error.config; // 401未授权且未重试过,尝试刷新令牌 if (error.response.status === 401 && !originalRequest._retry) { originalRequest._retry = true; const { auth } = store.getState(); // 调用刷新令牌接口 const refreshRes = await axios.post('/auth/refresh', { refreshToken: auth.refreshToken, }); // 更新Store中的令牌 store.dispatch({ type: 'auth/updateToken', payload: refreshRes.data, }); // 重新设置请求头并重试 originalRequest.headers.Authorization = `Bearer ${refreshRes.data.token}`; return api(originalRequest); } return Promise.reject(error); } ); export default api;
关键注意事项
- 确保App入口文件(比如
App.js)使用的是同一个store和persistor:
// App.js import { Provider } from 'react-redux'; import { PersistGate } from 'redux-persist/integration/react'; import { store, persistor } from './store'; import MainScreen from './screens/MainScreen'; export default function App() { return ( <Provider store={store}> <PersistGate loading={null} persistor={persistor}> <MainScreen /> </PersistGate> </Provider> ); }
- 绝对不要在
api.js中重新调用configureStore(),这会创建一个全新的、未持久化的空Store,导致拿不到数据。
内容的提问来源于stack exchange,提问作者Majid Lotfinia
相关产品推荐
相关产品推荐

