在React Native中将Redux数据持久化
问题在开发
解决首先,在建立redux store时,除了常规会用到的各种中间件以外,我们需要额外引入 // @flow import { createStore,applyMiddleware,compose } from 'redux'; import { autoRehydrate } from 'redux-persist'; import createSagaMiddleware from 'redux-saga'; import rootReducer from '../Reducers/'; import sagas from '../Sagas/'; import RehydrationServices from '../Services/RehydrationServices'; import ReduxPersist from '../Config/ReduxPersist'; import Config from '../Config/DebugConfig'; // 屏蔽flow误报警 declare var console: any; // 添加saga中间件 let middleware = []; const sagaMiddleware = createSagaMiddleware(); middleware.push(sagaMiddleware); export default () => { let store = {}; // 根据配置要求采用Reactotron或者原生store const createAppropriateStore = Config.useReactotron ? console.tron.createStore : createStore; if (ReduxPersist.active) { // 如果配置中要求采用持久化 const enhancers = compose( applyMiddleware(...middleware),autoRehydrate() ); store = createAppropriateStore( rootReducer,enhancers ); // 启动持久化 RehydrationServices.updateReducers(store); } else { // 如果配置中不要求采用持久化 const enhancers = compose( applyMiddleware(...middleware),); store = createAppropriateStore( rootReducer,enhancers ); } // 运行saga sagaMiddleware.run(sagas); return store; }; 代码中又对其他几段代码做了依赖,其中放在 // @flow import { combineReducers } from 'redux'; import LoginReducer from './LoginReducer'; import ActivitiesReducer from './ActivitiesReducer'; import ActivityReducer from './ActivityReducer'; import ResourcesReducer from './ResourcesReducer'; import NewsesReducer from './NewsesReducer'; export default combineReducers({ login: LoginReducer,activities: ActivitiesReducer,activity: ActivityReducer,resources: ResourcesReducer,newses: NewsesReducer,}); // 添加persist黑名单,以下这些reducer不需要持久化 export const persistentStoreBlacklist = [ 'activities','activity','resources','newses',]; 设置好黑名单之后,可以开始真正启用持久化了,这部分代码放在 // @flow import { AsyncStorage } from 'react-native'; import { persistStore } from 'redux-persist'; import ReduxPersist from '../Config/ReduxPersist'; const updateReducers = (store: any) => { const reducerVersion = ReduxPersist.reducerVersion; const config = ReduxPersist.storeConfig; // 按照配置要求自动持久化reducer persistStore(store,config); AsyncStorage.getItem('reducerVersion').then((localVersion) => { // 从本地存储取出reducer版本并比较 if (localVersion !== reducerVersion) { // 如果本地存储中的reducer版本与配置文件中的reducer版本不同,则需要清理持久化数据 persistStore(store,config,() => { persistStore(store,config); }).purge([]); // 清理成功,将本地存储中的reducer版本设为配置文件中的reducer版本 AsyncStorage.setItem('reducerVersion',reducerVersion); } }).catch(() => AsyncStorage.setItem('reducerVersion',reducerVersion)); } export default {updateReducers}; 这里要取 // @flow import { AsyncStorage } from 'react-native'; import immutablePersistenceTransform from '../Store/ImmutablePersistenceTransform'; import { persistentStoreBlacklist } from '../Reducers/'; const REDUX_PERSIST = { active: true,// 是否采用持久化策略 reducerVersion: '2',// reducer版本,如果版本不一致,将刷新整个持久化仓库 storeConfig: { storage: AsyncStorage,// 采用本地异步存储,react-native必须 blacklist: persistentStoreBlacklist,// 从根reducer获取黑名单,黑名单中的reducer不进行持久化保存 transforms: [immutablePersistenceTransform],// 重要,因为redux是immutable不可变的,此处必须将常规数据做变形,否则会失败 } }; export default REDUX_PERSIST; 这里用到了一个最重要的变形,否则整个过程不能成功,因为 // @flow import R from 'ramda'; import Immutable from 'seamless-immutable'; // 将redux中的immutable对象转为普通js对象,以便于持久化存储 const isImmutable = R.has('asMutable'); const convertToJs = (state) => state.asMutable({deep: true}); const fromImmutable = R.when(isImmutable,convertToJs); // 将普通js对象转为immutable不可变,以供redux使用 const toImmutable = (raw) => Immutable(raw); export default { out: (state: any) => { // 设置深度合并 state.mergeDeep = R.identity; // 从仓库中取出,进入内存时,转为immutable不可变 return toImmutable(state); },in: (raw: any) => { // 进入仓库时,将immutable不可变数据转为常规数据 return fromImmutable(raw); } }; 用法和常规使用方法一样,原先如何使用 案例完整代码可参见我在Github上的项目:Wecanmobile。觉得有帮助的话,请帮我打一颗星星。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |