企业级背景react-redux异步操纵实践

一、redux基本

redux

  1. 经由过程 dispatch(action) -> 中间件 -> reducer处置惩罚数据 -> 转变store -> 运用subscribe()监听store转变更新视图 的体式格局治理状况
  2. 将一切状况存储在一个store对象内里
  3. reducer为纯函数,而异步操纵因为效果的不确定性所以含有副作用,所以须要特别处置惩罚

react-redux

  1. 容器组件,担任治理数据和营业逻辑,不担任UI显现
  2. UI组件,供应UI显现,无状况即不运用this.state,状况悉数由this.props供应
  3. 由connect天生容器组件,每次store转变会挪用connect,connect吸收两个参数: mapStateToProps, mapDispatchToProps
  4. mapStateToProps,将状况映射到UI组件的props
  5. mapDispatchToProps,将dispatch要领映射到UI组件的props
  6. Provider组件,运用content API将store从顶层最先传到每一层component供connect运用

二、redux处置惩罚异步的中间件

redux-thunk

  1. redux-thunk中间件许可action是一个要领
  2. 中间件收到action后会实行action要领并将效果供应给reducer
  3. action杂沓致使不容易保护

redux-saga

  1. saga会监听action并基于这个action实行Effects操纵
  2. Effects供应天真的API,包含壅塞、非壅塞挪用,作废、守候、race等操纵
  3. 轻易断绝并实行异步操纵,并易于测试

三、redux-request-async-middleware

先从redux文档中的异步action提及,每一个接口挪用须要dispatch三个同步action,分别是:

  1. 一种关照 reducer 要求最先的 action。关于这类 action,reducer 能够会切换一下 state 中的 isFetching 标记。以此来通知 UI 来显现加载界面。
  2. 一种关照 reducer 要求胜利的 action。关于这类 action,reducer 能够会把吸收到的新数据合并到 state 中,并重置 isFetching。UI 则会隐蔽加载界面,并显现吸收到的数据。
  3. 一种关照 reducer 要求失利的 action。关于这类 action,reducer 能够会重置 isFetching。别的,有些 reducer 会保留这些失利信息,并在 UI 里显现出来。

也就是一个接口提议是如许的

dispatch(fetchPostsRequest(subject));
fetch(url).then(res => {
    dispatch(fetchPostsSuccess(subject, res));
}).catch(e => {
    dispatch(fetchPostsFailure(subject, e));
})

而我做的事变只是将这个操纵封装进中间件里,特别的处所在于:

  1. 一切的异步要求共用这三个action
  2. 用subject来辨别是哪个要求
  3. 将一切的效果都放到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
};
  1. 和redux-thunk一样,将要领放进action里
  2. 中间件阻拦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;
    }
}
  1. 将效果放入该subject对应下的response,假如毛病的话将毛病信息放入error当中
  2. isFetching示意当前的要求状况
  3. 别的还加入了当前的状况state和subject信息

将要求举行封装

const request = (subject, model, next) => {
    _dispatch(fetchPostsRequest(subject, model, next));
    return true;
};
  1. 写一个要领来提议FETCH_POSTS_REQUEST action
  2. 也就是说写要求的时刻不必再管action这东西了,直接挪用request要领

将效果举行封装

const getResponse = state =>
    state
    && state.response !== null
    && state.response;

const getLoading = (states = []) =>
    states.reduce((pre, cur) =>
        pre || (cur && cur.isFetching)
        , false)
    || false;
  1. 能够猎取效果和多个要求下loading的状况
  2. 有更多的操纵或许花样还能够继承封装,比方列表

运用要领redux-request-async-middleware

四、总结

  1. 运用了redux来举行状况治理,而并不须要编写redux那一套庞杂逻辑,最大水平的削减异步操纵的庞杂度
  2. 适用于前端经由过程接口来处置惩罚和存储数据的项目
  3. 接口由redux处置惩罚,而视图组件由内部state来处置惩罚,而外部只暴露简朴的接口来举行操纵,星散营业层和视图层
  4. 对照react 16.3 new content API,redux的上风在于热插播的中间件和纯函数reducer写法

更多文章 yjy5264.github.io

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