redux-persist持久化Set,Map

71 阅读2分钟

最近做项目的时候,发现需要持久化的序列是MAP,Set结构的数据;明明按照步骤做了持久化,但是结果获取到的数据却是{},一开始还以为是自己使用方式不正确,没有持久化数据,最后研究官方文档才知道,并不是任何数据都可以直接进行持久化的,对于不能直接进行序列化的数据需要使用TransFrom对数据进行处理;官方说明如下:

When the state object gets persisted, it first gets serialized with JSON.stringify(). If parts of your state object are not mappable to JSON objects, the serialization process may transform these parts of your state in unexpected ways. For example, the javascript [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) type does not exist in JSON. When you try to serialize a Set via JSON.stringify(), it gets converted to an empty object. Probably not what you want.

创建Store

import { configStore } from '@reduxjs/toolkit';
import userReducer from './slices/userSlice';
import dicomUploadSlice from './slices/dicomUploadSlice';

const store = configStore({
 reducer: {
     user:userReducer,
     dicomUpload: dicomUploadSlice,
 }
})

export type AppState = ReturnType<typeof store.getState>;
export type AppDispatch = ReturnType<typeof store.dispatch>;
export default store;
import { createSlice } from '@reduxjs/toolkit';

import { UploadListItem } from '@/pages/3d-data-center/types/index.ts';

interface uploadState {
  uploadData: UploadListItem[];
  isFullDisk: boolean;
}
const initialState: uploadState = {
  uploadData: [],
  isFullDisk: false,
};

export const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {
    updateIsFullDisk: (
      state,
      action: {
        payload: boolean;
      },
    ) => {
      console.log('update');
      state.isFullDisk = action.payload;
    },
  },
});
// 为每个 case reducer 函数生成 Action creators
export const {  updateIsFullDisk } = userSlice.actions;
export default userSlice.reducer;

加入redux-persist后

import { configStore } from '@reduxjs/toolkit';
import {combineReducers} from 'redux';

import userReducer from './slices/userSlice';
import dicomUploadSlice from './slices/dicomUploadSlice';
/* 持久化缓存 */
import {persistReducer,persistStore} form 'redux-persist'
import storage from 'redux-persist/es/storage'

/* 缓存数据配置 */
const persistConfig = {
    key:'root', //LocalStorage中显示未persist:root:{};
    storage,
    blacklist:['dicomUpload']//写在这个数组里的数据不会存在storage
}

const reducers = combineReducers({
    user:userReducer,
    dicomUpload: dicomUploadSlice,
})
const persistReducer = persistReducer(persistConfig, reducers)

const store = configStore({
 reducer: persistReducer ,
 middleware:(getDefaultMiddleware) =>
      getDefaultMiddleware({
        serializableCheck: false,
      }),
})

//记得包裹
export const persistor = persistStore(store);

export type AppState = ReturnType<typeof store.getState>;
export type AppDispatch = ReturnType<typeof store.dispatch>;
export default store;

持久化Set结构数据

  • 首先,使用transform说明如何序列化,以及获取的时候如何转换成Set结构
import { createTransform } from 'redux-persist';
 
const SetTransform = createTransform(
  // transform state on its way to being serialized and persisted.
  (inboundState, key) => {
    // convert mySet to an Array.
    return { ...inboundState, mySet: [...inboundState.mySet] };
  },
  // transform state being rehydrated
  (outboundState, key) => {
    // convert mySet back to a Set.
    return { ...outboundState, mySetnew Set(outboundState.mySet) };
  },
  // define which reducers this transform gets called for.
  { whitelist: ['someReducer'] }
);
 
export default SetTransform;
  • 上述createTransform函数接受三个参数:
    • 第一个参数是”inbound“:入站函数,在进行持久化之前调用,表示如何对该数据进行序列化
    • 第二个参数是“outbound”出战函数,表示在获取持久化的数据后,如何转换成目标结构类型数据
    • 最后一个参数是配置对象,表示哪个“Key”字段属性使用该transform进行转换
  • persistConfig中使用transform
import storage from 'redux-persist/lib/storage';
import { SetTransform } from './transforms';

const persistConfig = {
  key: 'root',
  storage: storage,
  transforms: [SetTransform]
};

Map序列化(待测试后补上)

Store的使用

import Store, { AppState } from '@/store';

import { updateIsFullDisk } from '../../store/slices/dicomUploadSlice.ts';

import { useSelector } from 'react-redux';

  const getStorage = async () => {
   //使用更新函数
 Store.dispatch(updateIsFullDisk(true))
  };
  
 //获取值
  const isFullDisk = useSelector((state: AppState) => {
    return state.dicomUpload.isFullDisk;
  });