react 实现 redux 异步action - web and native, redux同构(1)

最近在公司做了一个webapp 用了react和redux

然后公司想用react-native 重构之前的app,而且要和webapp代码复用(主要是redux代码),界面还是web一套,native一套

项目结构问题

子模块

现在使用的是 git 的子模块功能,就相当于2个项目公用一个公共的目录 目录结构如下(common目录为子模块)

# 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-polyfill

# 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)

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 库的 ,具体的可以看我这篇文章

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 中一般定义一些默认值,但是如果要从本地拿数据再赋值 目前找不到什么好方法,待解决吧

{
    //web中可以这样写 native中就很难实现了
    timestamp: localStorage.getItem('approvalListData.timestamp') || { }
}

目前就碰到这些问题,之后有问题再更新~

    原文作者:yang_j_j
    原文地址: https://segmentfault.com/a/1190000008863998
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞