【问题标题】:Redux-Persist don't save store to localStorageRedux-Persist 不会将 store 保存到 localStorage
【发布时间】:2021-09-27 03:34:41
【问题描述】:

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);

app.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;
}

【问题讨论】:

  • “不起作用”不是一个好的问题陈述。请阅读How to Ask 以获取有关如何构建一个不太可能被否决和关闭的问题的提示。另外,不要使用 Stack Snippets,除非 a) 如果需要,您要将实际的 HTML 放入 HTML 框中(不是 JavaScript),并且 b) 当您单击“Run code sn-p”时它们会执行某些操作。跨度>
  • 使用 react-native-async-storage: github.com/react-native-async-storage/async-storage

标签: javascript reactjs redux persist


【解决方案1】:

上周我发现自己处于类似情况,就像你一样,我也在运行时注入减速器,这就是我最终发现导致此问题的原因。

解决方法就是在注入一个新的reducer后调用persistor.persit()方法。您可能需要为您正在使用的 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 extension 似乎隐藏了这个问题。所以我对任何使用 redux 的开发者的建议是:

确保您在测试期间至少禁用一次 REDUX DEVTOOLS 扩展, 否则,您应用的用户可能会遇到与您假设的应用不同的情况。

来源:

【讨论】:

    猜你喜欢
    • 2018-08-25
    • 2020-01-07
    • 2018-06-22
    • 2022-12-06
    • 2019-09-20
    • 1970-01-01
    • 1970-01-01
    • 2022-08-02
    • 1970-01-01
    相关资源
    最近更新 更多