react 實現 redux 異步action - web and native, redux同構(1)

最近在公司作了一個webapp 用了react和reduxreact

而後公司想用react-native 重構以前的app,並且要和webapp代碼複用(主要是redux代碼),界面仍是web一套,native一套ios

項目結構問題

子模塊

如今使用的是 git 的子模塊功能,就至關於2個項目公用一個公共的目錄 目錄結構以下(common目錄爲子模塊)git

# web 項目

root
--client //web 項目代碼
----libs //本身寫的模塊
------storage.js //web數據模塊

--common //子模塊
----imgs // 圖片目錄
----redux // redux 目錄
------actions
------data
------reducers


# react-native 項目

root
--client //web 項目代碼
----libs //本身寫的模塊
------storage.js //native數據模塊

--common //子模塊
----imgs // 圖片目錄
----redux // redux 目錄
------actions
------data
------reducers

babel 配置

web端

# .babelrc
{
    "presets": ["react", "es2015", "stage-3"]
}

還要在入口文件處引入babel-polyfillweb

# index.js
import 'babel-polyfill'

native端

# .babelrc
{
    //這個能夠兼容 async function
    "presets": ["react-native-stage-0"]
}

redux 問題

使用的redux庫

import promiseMiddleware from 'redux-promise';
import axiosMiddleware from 'redux-axios-middleware';

const enhancers = compose(
    applyMiddleware(
        promiseMiddleware, //異步action 中間件
        axiosMiddleware(axios), //axios 中間件
    )
);

action

export function messageList() {
    let local = localStorage.getItem('timestamp') || '0'
    
    return {
        type: 'MESSAGE_LIST',
        payload: {
            request: {
                method: 'get',
                url: '[url]' + '?timestamp=' + local
            },
        }
    }
}

以前在寫web端的時候 有過在aciton裏獲取localstorage中的數據,到了react-native中就碰到問題了,由於react-native中沒有找到同步獲取本地數據的方法,因此以前的代碼就不能複用了,引入redux-promise這個庫解決異步action的問題,它可讓action的返回值是promise就把本地存儲封裝一下讓2端均可以用一套代碼。代碼以下(web也需封裝一下,但不用async)redux

import storage from '../../../client/libs/storage.js' // 
export async function messageList() {
    let local = await storage.getItem('timestamp')
    
    return {
        type: 'MESSAGE_LIST',
        payload: {
            request: {
                method: 'get',
                url: '[url]' + '?timestamp=' + local
            },
        }
    }
}


# storage.js native
import { AsyncStorage } from 'react-native'

export default {
  getItem : async function (key){
    let value = await AsyncStorageGetItem(key)
    return value
  }
}

async function AsyncStorageGetItem(key) {
  return new Promise((resolve,reject)=>{
    AsyncStorage.getItem(key, function (value) {
      resolve(value)
    })
  })
}
# storage.js native end


# storage.js web
export default {
  getItem : function (key){
    return JSON.parse(localStorage.getItem(key))
  }
}
# storage.js web end

reducers

目前沒有找到在 reducers 中使用異步操做的方案,因此只能取巧的把reducers中須要用到的本地數據在actions時傳入,像下面這樣 aciton.meta.previousAction 這個是 redux-axios-middleware 庫的 ,具體的能夠看我這篇文章axios

export async function messageList() {
    let local = await storage.getItem('timestamp')
    let reducersData = await storage.getItem('[key]')
    
    return {
        type: 'MESSAGE_LIST',
        payload: {
            request: {
                method: 'get',
                url: '[url]' + '?timestamp=' + local
            },
        },
        reducersData: reducersData
    }
}


case 'MESSAGE_LIST':
    return state;
case 'MESSAGE_LIST_SUCCESS':
    // 從上一個action中獲取數據
    let previousActionData = aciton.meta.previousAction.reducersData
    
    return state;
case 'MESSAGE_LIST_FAIL':
    return state;

data

data 中通常定義一些默認值,可是若是要從本地拿數據再賦值 目前找不到什麼好方法,待解決吧segmentfault

{
    //web中能夠這樣寫 native中就很難實現了
    timestamp: localStorage.getItem('approvalListData.timestamp') || { }
}

目前就碰到這些問題,以後有問題再更新~react-native

相關文章
相關標籤/搜索