旺仔小糖

RTK数据丢失解决方案 a year ago

react
2397个字符
共有202人围观

Redux虽然很好用,但是有个致命的缺陷 - 就是客户端一旦刷新页面,Redux的数据就会丢失,单页面页面体验就会大打折扣。我们总不能天天祈祷客户千万不要刷新浏览器吧

原因分析: 因为Redux存储在内存中,而不是持久存储在硬盘上。因此,当页面刷新时,Redux就会重置到初始状态。

解决方案: 解决这个问题的方法是将Redux存储到本地存储中,例如使用localStorage, 可以将Redux存储到localStorage中,并在页面加载时从localStorage中读取数据并将其应用到Redux状态中。这样即使刷新页面,Redux数据也会被保留。

网上通用的做法是使用 Redux Persist

相比RTK,使用Redux Persist只会影响2个文件:

  • 入口文件
  • store的创建

下面是vite的最终配置:

//main.tsx
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'
import { store } from './store'
import { Provider } from 'react-redux'
import { PersistGate } from 'redux-persist/integration/react';
import { persistStore } from 'redux-persist';

//https://github.com/rt2zz/redux-persist
const persistor = persistStore(store);

ReactDOM.createRoot(document.getElementById('root')!).render(
  <Provider store={store}>
    <PersistGate loading={null} persistor={persistor}>
        <App />
      </PersistGate>
  </Provider>,
)
//store/index.tsx
import { combineReducers, configureStore } from '@reduxjs/toolkit'
import storage from 'redux-persist/lib/storage';
import { persistReducer } from 'redux-persist';
import countSlice from './features/countSlice'

// combineReducers合并reducer
const reducers = combineReducers({
  count: countSlice
});

const persistConfig = {
  key: 'root',
  storage,
  blacklist: ['navigation'] // navigation will not be persisted
};

const persistedReducer = persistReducer(persistConfig, reducers);

export const store = configureStore({
  reducer: persistedReducer,
  // https://redux-toolkit.js.org/usage/usage-guide#working-with-non-serializable-data
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: {
        // Ignore these action types
        ignoredActions: ['persist/PERSIST'],
        // Ignore these field paths in all actions
        // ignoredActionPaths: ['meta.arg', 'payload.timestamp'],
        // Ignore these paths in the state
        // ignoredPaths: ['items.dates'],
      },
    }),
});

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch

完整demo: https://gitlab.scott-xiong.com/scott-x/rtk-persist