简体   繁体   English

如何使用 redux-toolkit 配置 redux-persist?

[英]How to configure redux-persist with redux-toolkit?

I have configured redux-persist with a traditional react-redux setup like this:我已经使用传统的 react-redux 设置配置了 redux-persist,如下所示:

onst persistConfig = {
  key: 'root',
  storage,
  whitelist: ['todos'],
};

const persistedReducer = persistReducer(persistConfig, reducer);

const store = createStore(
  persistedReducer,
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);

const persistor = persistStore(store);

// wrapper
const StateProvider = ({ children }) => {
  return (
    <Provider store={store}>
      <PersistGate loading={<div>Loading...</div>} persistor={persistor}>
        {children}
      </PersistGate>
    </Provider>
  );
};

But, how can I configure it with redux-toolkit?但是,如何使用 redux-toolkit 配置它? So far I have tried this:到目前为止,我已经尝试过:

const persistedReducer = persistReducer(persistConfig, todoreducer);
const store = configureStore({
  reducer: {
    todos: persistedReducer,
  },
});

const persistor = persistStore(store);

// wrapper
const StateProvider = ({ children }) => {
  return (
    <Provider store={store}>
      <PersistGate loading={<div>Loading...</div>} persistor={persistor}>
        {children}
      </PersistGate>
    </Provider>
  );
};

But, It is not working.但是,它不起作用。 I can't get the todos by const todos = useSelector(state => state.todos);我无法通过 const todos const todos = useSelector(state => state.todos);

it returns undefined.它返回未定义。

store.js store.js

import {configureStore} from '@reduxjs/toolkit';
import storage from 'redux-persist/lib/storage'
import {combineReducers} from "redux"; 
import { persistReducer } from 'redux-persist'
import thunk from 'redux-thunk'

const reducers = combineReducers({
 //...            
});

const persistConfig = {
    key: 'root',
    storage
};

const persistedReducer = persistReducer(persistConfig, reducers);


const store = configureStore({
    reducer: persistedReducer,
    devTools: process.env.NODE_ENV !== 'production',
    middleware: [thunk]
});

export default store;

Index/App.js索引/App.js

import store from './app/store';
import { PersistGate } from 'redux-persist/integration/react'
import { persistStore } from 'redux-persist'

let persistor = persistStore(store);

    <Provider store={store}>
        <PersistGate loading={null} persistor={persistor}>
        <App/>
        </PersistGate>
    </Provider>,

There's now a guide in the Redux Toolkit docs that will help you with this, as well as providing advice for purging the persisted state and working with RTK Query .现在Redux Toolkit 文档中有一个指南可以帮助您解决此问题,并提供有关清除持久状态和使用RTK Query的建议。

It also has some code you'll want to copy and paste to ignore the action types react-persist dispatches.它还有一些代码,您需要复制和粘贴以忽略动作类型react-persist调度。 This will stop it throwing error messages (I was getting the error A non-serializable value was detected in an action, in the path: `register`. when I ran my React Native app with Expo).这将阻止它抛出错误消息(当我使用 Expo 运行我的 React Native 应用程序时,我收到错误A non-serializable value was detected in an action, in the path: `register`. )。

At time of writing, their code sample looks like this:在撰写本文时,他们的代码示例如下所示:

import { configureStore } from '@reduxjs/toolkit'
import {
  persistStore,
  persistReducer,
  FLUSH,
  REHYDRATE,
  PAUSE,
  PERSIST,
  PURGE,
  REGISTER,
} from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import { PersistGate } from 'redux-persist/integration/react'

import App from './App'
import rootReducer from './reducers'

const persistConfig = {
  key: 'root',
  version: 1,
  storage,
}

const persistedReducer = persistReducer(persistConfig, rootReducer)

const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: {
        ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
      },
    }),
})

let persistor = persistStore(store)

ReactDOM.render(
  <Provider store={store}>
    <PersistGate loading={null} persistor={persistor}>
      <App />
    </PersistGate>
  </Provider>,
  document.getElementById('root')
)

When using TypeScript with stateReconciles option from persistConfig , you need a little type shim to avoid将 TypeScript 与stateReconciles中的persistConfig选项一起使用时,您需要一些类型的填充程序来避免

  • a) unknown generic inference a) unknown的通用推理
persistReducer<unknown, AnyAction>

Argument of type 'Reducer<CombinedState<{ ... }>, AnyAction>' is not assignable to parameter of type 'Reducer<unknown, AnyAction>'.
  Types of parameters 'state' and 'state' are incompatible.
    Type 'unknown' is not assignable to type 'CombinedState<{ ... }>'.ts(2345)

  • b) circular type reference b) 循环类型引用
const persistConfig = {
  stateReconciles: hardSet as RootState,
}

export type RootState = ReturnType<typeof store.getState> // Type alias 'RootState' circularly references itself.

The solution is in the extracted type CombinedState , as follows:解在提取的类型CombinedState中,如下:

import type { Reducer } from '@reduxjs/toolkit'
import { configureStore, combineReducers } from '@reduxjs/toolkit'
import { persistStore, persistReducer } from 'redux-persist'
import * as rp from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import hardSet from 'redux-persist/lib/stateReconciler/hardSet'

import createCollectionForm from './slices/CollectionFormSlice'
import auth from './slices/AuthSlice'

const persistConfig = {
  key: 'root',
  storage,
  stateReconciles: hardSet as (inboundState: CombinedState) => CombinedState,
  version: 1,
}

type CombinedState = typeof rootReducer extends Reducer<infer U, any> ? U : never

const rootReducer = combineReducers({
  auth,
  createCollectionForm,
})

const persistedReducer = persistReducer(persistConfig, rootReducer)

export const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: {
        ignoredActions: [rp.FLUSH, rp.REHYDRATE, rp.PAUSE, rp.PERSIST, rp.PURGE, rp.REGISTER],
      },
    }),
})

export const persistor = persistStore(store)


export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch

in store.js在 store.js 中

import { configureStore } from "@reduxjs/toolkit";
import storage from "redux-persist/lib/storage";
import { persistReducer } from "redux-persist";
import { combineReducers } from "redux";

const persistConfig = {
  key: "root",
  version: 1,
  storage,
  // if you do not want to persist this part of the state
  blacklist: ['omitedPart']
};

const reducer = combineReducers({
  cart: CartReducer,
  // not persisting this reducer
  omitedPart:OmitReducer
});
// this ensures your redux state is saved to persisted storage whenever it changes
// we pass this to the store
const persistedReducer = persistReducer(persistConfig, reducer);

const store = configureStore({
  reducer: persistedReducer,
});

export default store;

in your root component, index.js在你的根组件中,index.js

import { Provider } from "react-redux";
import store from "./redux/store";
import { PersistGate } from "redux-persist/integration/react";
import { persistStore } from "redux-persist";

let persistor = persistStore(store);

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      //PersistGate delays the rendering of UI until the persisted state has been retrrieved and saved to redux
      <PersistGate persistor={persistor}>
        <App />
      </PersistGate>
    </Provider>
  </React.StrictMode>,
  document.getElementById("root")
);

I just tried this with the exact similar setup and it seemed to work.我只是用完全相同的设置尝试了这个,它似乎工作。 If it's helpful, I'm on "@reduxjs/toolkit": "^1.4.0", , "redux-persist": "^6.0.0" , and "react-redux": "^7.2.1" .如果有帮助,我在"@reduxjs/toolkit": "^1.4.0", , "redux-persist": "^6.0.0""react-redux": "^7.2.1"上。 HTH. HTH。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM