React游戏应用API数据缓存与离线运行方案咨询
基于RTK Query实现离线优先的游戏数据缓存方案
针对你的需求——持久化1000个API对象到localStorage、24小时自动更新、离线 fallback,用RTK Query(你已熟悉的工具)是最适配的现代化方案,以下是具体实现步骤:
1. 配置RTK Query缓存持久化到localStorage
RTK Query默认是内存缓存,结合redux-persist可以将缓存永久存储到localStorage:
依赖安装(若未安装)
npm install @reduxjs/toolkit react-redux redux-persist
核心代码实现
// store.js import { configureStore } from '@reduxjs/toolkit'; import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import { persistReducer, persistStore } from 'redux-persist'; import storage from 'redux-persist/lib/storage'; // 默认使用localStorage // 1. 定义游戏API切片 const gameApi = createApi({ reducerPath: 'gameApi', baseQuery: fetchBaseQuery({ baseUrl: 'https://myapi/' }), tagTypes: ['GameObject'], // 标记数据类型,方便后续更新 endpoints: (builder) => ({ // 获取单个游戏对象 getGameObject: builder.query({ query: (name) => `${name}`, // 核心缓存规则 staleTime: 86400000, // 24小时内数据视为"新鲜",不自动触发更新 keepUnusedDataFor: 31536000, // 缓存保留1年(近似永久存储) // 为每个对象生成唯一标签 providesTags: (_, __, name) => [{ type: 'GameObject', id: name }], // 网络失败时不抛出错误,直接沿用缓存 onQueryStarted: async (name, { queryFulfilled }) => { try { await queryFulfilled; } catch (err) { console.log(`无法更新${name},使用本地缓存数据`); } }, }), }), }); // 2. 配置redux-persist持久化规则 const persistConfig = { key: 'gameApiCache', storage, whitelist: ['queries', 'mutations'], // 仅持久化缓存数据,排除其他API状态 }; // 3. 包装API切片的reducer为持久化版本 const persistedGameApiReducer = persistReducer(persistConfig, gameApi.reducer); // 4. 创建Redux Store export const store = configureStore({ reducer: { [gameApi.reducerPath]: persistedGameApiReducer, // 其他自定义reducer可在此添加 }, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: false, // 关闭序列化检查,避免redux-persist的警告 }).concat(gameApi.middleware), }); // 5. 创建持久化Store实例 export const persistor = persistStore(store); // 导出RTK Query生成的hooks export const { useGetGameObjectQuery } = gameApi;
应用入口配置
在App根组件中用PersistGate包裹,确保缓存加载完成后再渲染应用:
// App.jsx import { Provider } from 'react-redux'; import { PersistGate } from 'redux-persist/integration/react'; import { store, persistor } from './store'; function App() { return ( <Provider store={store}> <PersistGate loading={null} persistor={persistor}> {/* 你的游戏应用组件 */} </PersistGate> </Provider> ); } export default App;
2. 核心逻辑说明
- 24小时自动更新:
staleTime设置为24小时,超过时间后,RTK Query会在后台自动发起API请求更新数据,同时返回旧缓存;如果离线,直接沿用旧数据。 - 永久缓存:
keepUnusedDataFor设置为1年,确保缓存不会被自动清理。 - 离线 fallback:RTK Query默认会优先返回缓存数据,仅在缓存不存在时才发起网络请求;网络失败时,不会抛出错误,直接保留缓存数据。
3. 手动触发更新(可选)
如果需要手动刷新某个对象,可使用生成的hook提供的refetch方法:
// 组件中使用 import { useGetGameObjectQuery } from './store'; function GameObject({ name }) { const { data, refetch, isLoading } = useGetGameObjectQuery(name); if (isLoading && !data) return <div>加载中...</div>; return ( <div> <h3>{data.name}</h3> <button onClick={() => refetch()}>刷新数据</button> </div> ); }
4. React Query替代方案(若考虑切换)
如果你想尝试React Query,配置更简洁,用@tanstack/react-query-persist-client插件直接实现localStorage持久化:
// App.jsx import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { persistQueryClient } from '@tanstack/react-query-persist-client'; import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister'; const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 86400000, cacheTime: 31536000, retry: false, // 离线时不重试 refetchOnWindowFocus: false, // 窗口聚焦不自动刷新 }, }, }); const persister = createSyncStoragePersister({ storage: window.localStorage }); persistQueryClient({ queryClient, persister }); function App() { return ( <QueryClientProvider client={queryClient}> {/* 应用组件 */} </QueryClientProvider> ); }
组件中使用
import { useQuery } from '@tanstack/react-query'; function GameObject({ name }) { const { data, isLoading } = useQuery({ queryKey: ['gameObject', name], queryFn: () => fetch(`https://myapi/${name}`).then(res => res.json()), }); if (isLoading && !data) return <div>加载中...</div>; return <div>{data.name}</div>; }
注意事项
- 确保API返回的对象可以被localStorage序列化(无函数、循环引用等)。
- localStorage有5MB左右的容量限制,1000个对象若体积过大,可考虑切换到IndexedDB,但需额外适配。
- RTK Query的缓存键基于
name参数自动生成,每个对象的缓存相互独立。
内容的提问来源于stack exchange,提问作者vogomatix
相关产品推荐
相关产品推荐

