在React Native中將Redux資料持久化

2021-09-16 20:05:40 字數 4316 閱讀 5027

在開發react-native過程中,使用redux儲存狀態遷移已基本成為乙個標準做法。使用者登入時的狀態變更,會帶來redux狀態遷移,而應用程式的其他部分也需要了解使用者是否已登入以及相關的登入資訊,只要軟體不退出,通過reducer我們總是能感知到變化的。但問題是軟體退出後,reducer從記憶體中消失,使用者如果再次開啟軟體,還需要登入。簡單做法是把登入的token等資訊儲存在react-native提供的asyncstorage裡,但這樣一來就打斷了和redux的聯絡。有沒有可能直接把redux的資訊儲存在asyncstorage裡呢?這樣一來我們就既解決了記住使用者登入資訊的問題,同時又不打破redux的優良結構。

github上已經有現成的redux-persist包以解決redux持久化問題,但在實際使用過程中,還有很多問題需要解決。具體來說,redux-persist這個包提供的是通用解決方案,也可以用於react.js,如果你要用在react-native中的話,需要指定asyncstorage,另外,雖然它還額外提供了兩個transform外掛程式redux-persist-transform-immutable和redux-persist-immutable,但這兩個外掛程式目前使用起來還是有問題沒有解決,為了盡快用上redux-persist,可以使用以下方案。

首先,在建立redux store時,除了常規會用到的各種中介軟體以外,我們需要額外引入redux-persist裡的autorehydrate增強器,然後啟動持久化。這部分**儲存在store目錄下的store.js檔案中:

// @flow

import 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 () => ;

// 根據配置要求採用reactotron或者原生store

if (reduxpersist.active) else

// 執行saga

sagamiddleware.run(sagas);

return store;

};

**中又對其他幾段**做了依賴,其中放在reducers目錄下的index.js中定義了黑名單,放在黑名單中的reducer是不進行持久化的:

// @flow

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

// 新增persist黑名單,以下這些reducer不需要持久化

export const persistentstoreblacklist = [

'activities',

'activity',

'resources',

'newses',

];

設定好黑名單之後,可以開始真正啟用持久化了,這部分**放在services目錄下的rehydrationservices.js裡:

// @flow

import from 'react-native';

import from 'redux-persist';

import reduxpersist from '../config/reduxpersist';

const updatereducers = (store: any) => ).purge();

// 清理成功,將本地儲存中的reducer版本設為配置檔案中的reducer版本

asyncstorage.setitem('reducerversion', reducerversion);

}}).catch(() => asyncstorage.setitem('reducerversion', reducerversion));

}export default ;

這裡要取config目錄下的reduxpersist.js檔案的配置:

// @flow

import from 'react-native';

import immutablepersistencetransform from '../store/immutablepersistencetransform';

import from '../reducers/';

const redux_persist =

};export default redux_persist;

這裡用到了乙個最重要的變形,否則整個過程不能成功,因為redux裡的物件都是immutable不可變的,我們在將它們持久化的時候,必須轉成mutable可變的常規js物件,而從本地儲存中取出來進入redux迴圈的時候,又需要將它們變成immutable的。下面這段**要放在store目錄下的immutablepersistencetransform.js中:

// @flow

import r from 'ramda';

import immutable from 'seamless-immutable';

// 將redux中的immutable物件轉為普通js物件,以便於持久化儲存

const isimmutable = r.has('asmutable');

const converttojs = (state) => state.asmutable();

const fromimmutable = r.when(isimmutable, converttojs);

// 將普通js物件轉為immutable不可變,以供redux使用

const toimmutable = (raw) => immutable(raw);

export default ,

in: (raw: any) =>

};

和常規使用方法一樣,原先如何使用redux,現在還是怎麼樣用,應用程式啟動時,直接判斷儲存使用者登入資訊的reducer裡有沒有值就行了,如果沒有的話,調出登入介面,如果有的話,直接從reducer中取值。是不是很方便呢?

完整**可參見我在github上的專案:wecanmobile。覺得有幫助的話,請幫我打一顆星星。

React Native在真機執行(IOS)

如果之前在模擬器除錯過,換成真機執行的時候務必關閉模擬器 需要修改的配置 bundle identifier 修改為 com.soho3q 如果上來就執行的話,會報錯 改完介面 修改如下 確認目標裝置的系統版本一致 同樣也要確認tests測試用例專案下的配置 開啟info.plist檔案 值改為ye...

MQTT在react native中的執行

mqtt 1 什麼是mqtt?mqtt message queuing telemetry transport,訊息佇列遙測傳輸協議 是一種基於發布 訂閱 publish subscribe 模式的 輕量級 通訊協議,輕量,高效,具體,請參考菜鳥教程 2 mqtt的幾個重要概念 3 mqtt的幾個方...

在php中將access轉化到mysql

最近將 jky 的資料從mypower的access轉化到了dedecms的mysql,一些問題總結一下。connstr driver microsoft access driver mdb dbq realpath pe.mdb connid odbc connect connstr,sql cu...