资讯专栏INFORMATION COLUMN

企业级后台react-redux异步操作实践

duan199226 / 1724人阅读

摘要:一种通知请求成功的。对于这种,可能会把接收到的新数据合并到中,并重置。另外,有些会保存这些失败信息,并在里显示出来。

一、redux基础 redux

通过 dispatch(action) -> 中间件 -> reducer处理数据 -> 改变store -> 使用subscribe()监听store改变更新视图 的方式管理状态

将所有状态存储在一个store对象里面

reducer为纯函数,而异步操作由于结果的不确定性所以含有副作用,所以需要特殊处理

react-redux

容器组件,负责管理数据和业务逻辑,不负责UI呈现

UI组件,提供UI呈现,无状态即不使用this.state,状态全部由this.props提供

由connect生成容器组件,每次store改变会调用connect,connect接收两个参数: mapStateToProps, mapDispatchToProps

mapStateToProps,将状态映射到UI组件的props

mapDispatchToProps,将dispatch方法映射到UI组件的props

Provider组件,使用content API将store从顶层开始传到每一层component供connect使用

二、redux处理异步的中间件 redux-thunk

redux-thunk中间件允许action是一个方法

中间件收到action后会执行action方法并将结果提供给reducer

action混乱导致不易维护

redux-saga

saga会监听action并基于这个action执行Effects操作

Effects提供灵活的API,包括阻塞、非阻塞调用,取消、等待、race等操作

方便隔离并执行异步操作,并易于测试

三、redux-request-async-middleware 先从redux文档中的异步action说起,每个接口调用需要dispatch三个同步action,分别是:

一种通知 reducer 请求开始的 action。对于这种 action,reducer 可能会切换一下 state 中的 isFetching 标记。以此来告诉 UI 来显示加载界面。

一种通知 reducer 请求成功的 action。对于这种 action,reducer 可能会把接收到的新数据合并到 state 中,并重置 isFetching。UI 则会隐藏加载界面,并显示接收到的数据。

一种通知 reducer 请求失败的 action。对于这种 action,reducer 可能会重置 isFetching。另外,有些 reducer 会保存这些失败信息,并在 UI 里显示出来。

也就是一个接口发起是这样的

dispatch(fetchPostsRequest(subject));
fetch(url).then(res => {
    dispatch(fetchPostsSuccess(subject, res));
}).catch(e => {
    dispatch(fetchPostsFailure(subject, e));
})
而我做的事情只是将这个操作封装进中间件里,特殊的地方在于:

所有的异步请求共用这三个action

用subject来区分是哪一个请求

将所有的结果都放到store.requests里

中间件源码
export const reduxRequest = store => next => action => {
    let result = next(action);
    let { type, subject, model } = action;
    let _next = action.next;
    if(type === FETCH_POSTS_REQUEST) {
        model().then(response => {
            _next && _next(response);
            store.dispatch(fetchPostsSuccess(subject, response));
        }).catch(error => {
            console.error(error);
            store.dispatch(fetchPostsFailure(subject, error));
        });
    }
    return result
};

和redux-thunk一样,将方法放进action里

中间件拦截FETCH_POSTS_REQUEST action,并进行异步处理

reducer源码
export const requests = (state = {}, action) => {
    switch (action.type) {
        case FETCH_POSTS_REQUEST:
            return assign({},
                state,
                {
                    [action.subject]: {
                        isFetching: true,
                        state: "loading",
                        subject: action.subject,
                        response: null,
                        error: null,
                    }
                }
            );
        case FETCH_POSTS_FAILURE:
            return assign({},
                state,
                {
                    [action.subject]: {
                        isFetching: false,
                        state: "error",
                        subject: action.subject,
                        response: state[action.subject].response,
                        error: action.error,
                    }
                }
            );
        case FETCH_POSTS_SUCCESS:
            return assign({},
                state,
                {
                    [action.subject]: {
                        isFetching: false,
                        state: "success",
                        subject: action.subject,
                        response: action.response,
                    }
                }
            );
        case FETCH_POSTS_CLEAR:
            return assign({},
                state,
                {
                    [action.subject]: {
                        isFetching: false,
                        state: "cleared",
                        subject: null,
                        response: null,
                        error: null,
                    }
                }
            );
        default:
            return state;
    }
}

将结果放入该subject对应下的response,如果错误的话将错误信息放入error当中

isFetching表示当前的请求状态

另外还加入了当前的状态state和subject信息

将请求进行封装
const request = (subject, model, next) => {
    _dispatch(fetchPostsRequest(subject, model, next));
    return true;
};

写一个方法来发起FETCH_POSTS_REQUEST action

也就是说写请求的时候不用再管action这东西了,直接调用request方法

将结果进行封装
const getResponse = state =>
    state
    && state.response !== null
    && state.response;

const getLoading = (states = []) =>
    states.reduce((pre, cur) =>
        pre || (cur && cur.isFetching)
        , false)
    || false;

可以获取结果和多个请求下loading的状态

有更多的操作或者格式还可以继续封装,比如列表

使用方法redux-request-async-middleware 四、总结

使用了redux来进行状态管理,而并不需要编写redux那一套复杂逻辑,最大程度的减少异步操作的复杂度

适用于前端通过接口来处理和存储数据的项目

接口由redux处理,而视图组件由内部state来处理,而外部只暴露简单的接口来进行操作,分离业务层和视图层

对比react 16.3 new content API,redux的优势在于热插播的中间件和纯函数reducer写法

更多文章 yjy5264.github.io

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/108175.html

相关文章

  • react+react-router+react-redux全家桶小项目开发过程分享

    摘要:项目地址下载完项目然后即可基于的项目,主要是为了学习实战。数据都是固定的,从饿了么接口临时抓的,模拟了一个的异步数据延迟,感谢饿了么。详细信息可以看上面的官方文档,我这里就简单说一下我这个项目的应用。 react-ele-webapp 项目地址 :https://github.com/kliuj/reac... run 下载完项目npm install然后npm run dev 即可 ...

    zzir 评论0 收藏0
  • 尚学堂 react -后台管理系统开发流程

    摘要:项目开发准备描述项目技术选型接口接口文档测试接口启动项目开发使用脚手架创建项目开发环境运行生产环境打包运行管理项目创建远程仓库创建本地仓库配置将本地仓库推送到远程仓库在本地创建分支并推送到远程如果本地有修改新的同事克隆仓库如果远程修 day01 1. 项目开发准备 1). 描述项目 2). 技术选型 3). API接口/接口文档/测试接口 2. 启动项目开发 1). 使用react...

    lemon 评论0 收藏0
  • React 实践项目 (二) redux + immutable + redux-saga

    摘要:在上已经有接近的数了,是目前最热门的前端框架。惟一改变的办法是触发,一个描述发生什么的对象。对对象的任何修改或添加删除操作都会返回一个新的对象。从导入需要的类型初始化状态就是一个纯函数,接收旧的和,返回新的。 React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架。而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战! Re...

    amuqiao 评论0 收藏0
  • 干货 | React技术栈耕耘 —— Redux

    摘要:作者小沪江前端开发工程师本文为原创文章,有不当之处欢迎指出。于是,单一数据源规则实施起来,是规定用的顶层容器组件的来存储单一对象树,同时交给来管理。顾名思义,当更新时,的回调函数会更新视图层,以达到订阅的效果。 作者:小boy (沪江web前端开发工程师)本文为原创文章,有不当之处欢迎指出。转载请注明出处。文章示例代码:https://github.com/ikcamp/rea... ...

    LdhAndroid 评论0 收藏0
  • react-redux初探理解

    摘要:它的作用就是像它的名字那样,建立一个从外部的对象到组件的对象的映射关系。比如表示从整个的表示当前组件容器的用来建立组件的参数到方法的映射比如表示它定义了哪些用户的操作应该当作,传给。 最近做的项目加入了react-redux,对react-redux一直没理解透彻,最近有时间把react-redux梳理了一番,希望能够帮助到大家, 首先有这几个文件,action,reducer,sag...

    ziwenxie 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<