javascript - Redux-Persist 不会将 store 保存到 localStorage
问题描述
Redux-Persist 不会将 store 保存到 localStorage,有人有什么想法吗?
store.js
import { createInjectorsEnhancer } from 'redux-injectors';
import { applyMiddleware, createStore } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import createSagaMiddleware from 'redux-saga';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import { createReducer } from './createReducer';
export function configureStore() {
const sagaMiddleware = createSagaMiddleware();
const middlewares = [sagaMiddleware];
const persistConfig = {
key: 'root',
storage,
};
const enhancers = [
applyMiddleware(...middlewares),
createInjectorsEnhancer({
createReducer,
runSaga: sagaMiddleware.run,
}),
];
const persistedReducer = persistReducer(persistConfig, createReducer());
const store = createStore(persistedReducer, {}, composeWithDevTools(...enhancers));
const persistor = persistStore(store);
return { store, persistor };
}
createReducer.js
import { combineReducers } from 'redux';
export function createReducer(injectedReducers = {}) {
return combineReducers({
...injectedReducers,
});
}
成分:
import { bindActionCreators, Dispatch } from 'redux';
import { ActionType } from 'typesafe-actions';
import { useEffect } from 'react';
import { createStructuredSelector } from 'reselect';
import { connect } from 'react-redux';
import { useInjectReducer, useInjectSaga } from 'redux-injectors';
import * as Actions from './actions';
import { ComponentReducer } from './reducer';
import { ComponentSaga } from './saga';
function Component({ }: ComponentProps) {
useInjectReducer({ key: 'Component', reducer: ComponentReducer });
useInjectSaga({ key: 'Component', saga: ComponentSaga });
return <></>;
}
type ComponentProps- = {
// types
};
const mapDispatchToProps = (dispatch: Dispatch<ActionType<typeof Actions>>) =>
bindActionCreators(
{
// methods,
},
dispatch,
);
const mapStateToProps = createStructuredSelector({
// selectors
});
export default connect(mapStateToProps, mapDispatchToProps)(Component);
应用程序.js
import { Provider } from 'react-redux';
import { Router } from 'react-router';
import { PersistGate } from 'redux-persist/integration/react';
import App from './containers/App';
import { configureStore } from '../utils/configureStore';
import { history } from '../appHistory';
const { store, persistor } = configureStore();
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<Router history={history}>
<App />
</Router>
</PersistGate>
</Provider>
</React.StrictMode>,
document.getElementById('root'),
);
它看起来像一个正常的应用程序结构,但它不起作用。我认为 90% 的问题在于带有 redux-injectors 的动态注入减速器。我试过用老方法注入之类的,但还是没用。
/**
* Create the store with dynamic reducers
*/
import { createStore, applyMiddleware, compose } from 'redux';
import { fromJS } from 'immutable';
import { routerMiddleware } from 'connected-react-router/immutable';
import createSagaMiddleware from 'redux-saga';
import { persistStore, autoRehydrate } from 'redux-persist-immutable';
import createFilter from 'redux-persist-transform-filter-immutable';
import createReducer from './reducers';
const sagaMiddleware = createSagaMiddleware();
export default function configureStore(initialState = {}, history) {
// Create the store with two middlewares
// 1. sagaMiddleware: Makes redux-sagas work
// 2. routerMiddleware: Syncs the location/URL path to the state
const middlewares = [sagaMiddleware, routerMiddleware(history)];
const enhancers = [applyMiddleware(...middlewares)];
enhancers.push(autoRehydrate());
// If Redux DevTools Extension is installed use it, otherwise use Redux compose
/* eslint-disable no-underscore-dangle, indent */
const composeEnhancers =
process.env.NODE_ENV !== 'production' && typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({ trace: true })
: compose;
/* eslint-enable */
const store = createStore(createReducer(), fromJS(initialState), composeEnhancers(...enhancers));
if (process.env.NODE_ENV !== 'test') {
const stateFilter = createFilter('global', [
'abonent',
'version',
'products',
'showWorkSpaces',
'error',
'settings',
]);
window.persistor = persistStore(store, {
whitelist: ['global', 'sprinterSidebar'],
transforms: [stateFilter],
});
}
// Extensions
store.runSaga = sagaMiddleware.run;
store.injectedReducers = {}; // Reducer registry
store.injectedSagas = {}; // Saga registry
return store;
}
解决方案
就在上周,我发现自己遇到了类似的情况,就像你一样,我也在运行时注入了减速器,这就是我最终发现导致这个问题的原因。
persistor.persit()
解决方法就是在注入新的reducer后调用该方法。您可能需要查看如何为redux-injectors
您正在使用的库执行此操作。就我而言,我使用一个简单的函数来做到这一点:
/**
* dynamically injects a reducer at runtime
* @param key an identifier for this reducer
* @param reducer The reducer
* @param blacklist do not persist the reducer state
*/
const injectReducer = <RState>(key: string, reducer: Reducer<RState, AnyAction>, blacklist = false) => {
if (!(key in asyncReducers)) {
asyncReducers[key] = reducer;
if (blacklist) {
asyncBlacklist.push(key);
}
appStore.replaceReducer(createReducer(asyncReducers, asyncBlacklist));
storeEvents.emit("root-reducer-change"); // or persistor.persist()
}
};
storeEvents
是一个EventEmitter3
对象。
...这就是我注册监听器然后持久存储的地方:
export const store = { ...appStore, injectReducer };
export const persistor = persistStore(appStore);
storeEvents.on("root-reducer-change", () => persistor.persist());
另一个奇怪的(可能是最令人沮丧的)部分是为了理解发生了什么,安装了redux devtools 扩展似乎隐藏了这个问题。所以我对任何使用 redux 的开发者的建议是:
确保您在测试期间至少禁用一次 REDUX DEVTOOLS 扩展,否则您的应用程序的用户可能会遇到与您假设的应用程序不同的情况。
资料来源:
推荐阅读
- sql-server - 如何使用 Azure 托管实例配置 SSRS 配置?
- python - 使用 HoloViews+Bokeh 绘制连接到 HeatMap 的高斯分布
- java - 存储在垃圾收集过程中的引用对象的“年龄阈值”存储在哪里?
- php - Laravel 属于多返空
- r - 错误:无法组合`..1$A`
和`..2$A` > - xml - Dataweave:打开和关闭标签命名空间
- excel - 用VB.net打开Excel Office365 Doc
- java - 如果两个商店具有相同的 ID 并且他们希望与 Corp 同步,SymmetricDs 如何处理 ID 冲突
- youtube-api - 如何获取我订阅的频道的 ID?
- django - 如何在 django ORM 的 WHERE 子句上使用 CASE 语句进行查询?