一、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写法