首次页面加载时RTK createApi如何访问localStorage或env中的baseUrl配置
问题根因
你遇到的问题本质是代码执行时机顺序不匹配:
src/services/api.ts中的顶层代码会在模块导入时立刻执行,也就是你的localStorage.getItem操作远早于App.tsx中useEffect的执行时机- 首次加载时useEffect还没把.env的接口地址写入localStorage,createApi就已经完成初始化,自然读取不到正确值
解决方案
方案1:使用动态baseQuery(最推荐,兼容后续baseUrl变更)
不要在模块顶层固定baseUrl,而是在每次发起请求时动态读取redux store或localStorage中的最新值,RTK Query的baseQuery支持访问store全局状态:
// src/services/api.ts 修改后代码 import { fetchBaseQuery, createApi } from '@reduxjs/toolkit/query/react'; export const dataApis = createApi({ reducerPath: 'dataApis', baseQuery: async (args, api, extraOptions) => { // 优先从store取,其次取localStorage,保证拿到的是最新值 const baseUrl = api.getState().reducerSlice.apiEndpoint || localStorage.getItem(config.apiEndpoint) || ''; const baseQuery = fetchBaseQuery({ baseUrl }); return baseQuery(args, api, extraOptions); }, endpoints: (builder) => ({ // 原有接口定义完全不需要修改 }) })
这个方案的优势是就算后续运行时baseUrl发生变化,不需要重新初始化api,所有请求自动生效。
方案2:提前配置localStorage时机(改造成本最低,原有api代码无需调整)
把原来写在App.tsx useEffect里的env读取逻辑,提前到应用初始化、store/createApi初始化之前执行,保证api模块初始化时localStorage已经有值:
// src/main.tsx 入口文件修改 import React from 'react'; import ReactDOM from 'react-dom/client'; import { Provider } from 'react-redux'; import App from './App'; import { configureStore } from '@reduxjs/toolkit'; import { dataApis } from './services/api'; import { reducerSlice } from './redux/reducerSlice'; // 提前处理.env配置,在初始化store和api前完成localStorage写入 const myCustomEndpoint = window._env_.MYENDPOINT; if(myCustomEndpoint) { localStorage.removeItem('api'); localStorage.setItem('api', myCustomEndpoint); } // 再初始化store和api,此时api.ts顶层读取localStorage已经能拿到正确值 const store = configureStore({ reducer: { [reducerSlice.name]: reducerSlice.reducer, [dataApis.reducerPath]: dataApis.reducer, }, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(dataApis.middleware) }) // 最后挂载应用 ReactDOM.createRoot(document.getElementById('root')!).render( <Provider store={store}> <App /> </Provider> )
对应的可以删掉App.tsx里原来处理env的useEffect逻辑,避免重复执行。
内容的提问来源于stack exchange,提问作者Errand
相关产品推荐
相关产品推荐

