如何在Redux Toolkit中异步设置preloadedState?
问题解答
首先明确:configureStore的preloadedState必须是同步值,不能传入Promise或者异步函数,所以你直接把异步的loadStateFromStorage赋值给它是行不通的。下面给你两种更优雅的实现方式:
方案一:异步获取数据后再初始化Store(优化你当前的方案)
你现在的思路是对的,只是可以把代码封装得更整洁:
1. 封装状态加载与Store创建逻辑
在store.js里统一处理:
export const loadStateFromStorage = async () => { const result = await window.chrome.storage.local.get(["multitask-state"]); return result["multitask-state"] ? JSON.parse(result["multitask-state"]) : undefined; }; export const createStore = (preloadedState) => configureStore({ reducer: { tasks: taskReducer, timer: timerReducer }, preloadedState, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat([storeStateToStorage]) });
2. 入口文件异步初始化并渲染
// index.js import { loadStateFromStorage, createStore } from './store'; async function initApp() { const initialState = await loadStateFromStorage(); const store = createStore(initialState); root.render( <React.StrictMode> <Provider store={store}> <App /> </Provider> </React.StrictMode> ); } initApp();
这种方式逻辑清晰,完全贴合Redux的初始化流程,不会产生额外的状态同步问题。
方案二:先初始化空Store,再异步加载状态(适合不想延迟渲染的场景)
如果不想让App因加载状态而延迟渲染,可以先创建无预加载状态的Store,再在App挂载后通过dispatch action加载本地存储的状态:
1. 创建基础Store并添加加载状态的action
// store.js export const store = configureStore({ reducer: { tasks: taskReducer, timer: timerReducer }, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat([storeStateToStorage]) }); // 定义加载tasks状态的action export const loadTasksState = (state) => ({ type: 'tasks/loadState', payload: state }); // 在taskReducer中添加对应的处理逻辑 const taskReducer = createReducer(initialState, (builder) => { builder // 保留原有业务逻辑的case .addCase(loadTasksState, (state, action) => { // 根据需求合并或替换状态,示例为合并 return { ...state, ...action.payload }; }); }); // 同理可添加timer状态的加载action与reducer逻辑
2. 在App组件中异步加载并分发状态
// App.js import { useEffect } from 'react'; import { useDispatch } from 'react-redux'; import { loadTasksState } from './store'; function App() { const dispatch = useDispatch(); useEffect(() => { async function loadSavedState() { const result = await window.chrome.storage.local.get(["multitask-state"]); if (result["multitask-state"]) { const savedState = JSON.parse(result["multitask-state"]); dispatch(loadTasksState(savedState.tasks)); // 若有timer状态,同步dispatch对应的加载action } } loadSavedState(); }, [dispatch]); // 可在状态加载完成前显示加载提示 return ( <div className="app"> {/* 你的组件内容 */} </div> ); }
这种方式适合需要快速渲染App、后台加载状态的场景,用户不会看到长时间白屏,但需要处理状态加载前后的UI过渡(如加载态)。
内容的提问来源于stack exchange,提问作者wallop
相关产品推荐
相关产品推荐

