Redux
官方解释--是js应用的可预测状态的容,可以理解为全局数据状态管理工具,用来组件通信和数据共享等功能。
使用场景:
- 某个组件的状态需要共享
- 某个状态需要在多个地方用到
- 一个组件需要改变其他组件的状态
- 一个组件需要改变全局状态
总体来说,在涉及到状态的共享时,如果通过props一层层传递实在是太麻烦了,所以这时redux应运而生。redux主要包含三个部分:action、reducer和store。
action:
1.无法直接操作store中的数据,只能通过reducer去处理
2.action是一个对象,必须有一个type参数,这个参数类似一个枚举类型。
const demoAction = {
const json = axios.post(url: 'xxx', { dataObj: { id: 'xx' } }); // 异步请求
dispatch({ type: 'INSERT_INFO', json}); // 通过dispatch调用reducer
}
reducer
1.reducer是唯一可以操作store的地方
2.可以通过combineReducers({ reducer1, reducer2... })将多个reducer合并,防止在一个reducer中管理太多状态
const demoReducer = (state, action) => {
switch (action.type) {
case INSERT_INFO:
return { ...state, dataObj: action.json };
case TO_DO: {
return { ...state, xxx };
}
....
default:
return state;
}
}
store
1.使用createStore创建
2.提供subscribe、dispatch、getState方法
const demoStore = createStore(reducer);
store.dispatch(actions.INERT_INFO);
store.subcribe(() => {
console.info(store.getState());
})
react-redux
是为了让redux更好的适用于react而生的一个库,react-redux将组件分为容器组件和UI组件,容器组件处理逻辑,后者只负责显示和交互,状态交由外部控制。其中有两个核心:Provider和connect。
Provider
一般我们将顶层组件用Provider包括后,所有组件就都在react-redux的控制之下,但是store必须作为参数放到Provider组件中。
<Provider store={ store }>
<App />
</Provider>
connect
此方法作为高阶组件,可以将容器组件中定义的store和dispatch传递给UI组件。
connect(mapStatetoProps, mapDispatchToProps)(UI组件)
redux-saga
实际应用场景中,在action中调用reducer之前一般会进行一个类似ajax的异步请求操作,需要拿到异步请求的结果集后再进行reducer的操作,redux-saga就是优雅处理这件事的,用同步的方式写异步代码,可以公告的解决异步问题。
辅助函数
takeEvery
同一个action多次触发时,每次都会执行。还是以文中redux部分action代码为例。
const demoAction = {
// const json = axios.post(url: 'xxx', { dataObj: { id: 'xx' } }); // 异步请求
// dispatch({ type: 'INSERT_INFO', json}); // 通过dispatch调用reducer
function* demoAction() {
yield* takeEvery('INSERT_INFO', axions.post(url: 'xxx', params));
}
}
takeLastest
多次触发action时,我们只想得到最新请求的响应。
const demoAction = {
// const json = axios.post(url: 'xxx', { dataObj: { id: 'xx' } }); // 异步请求
// dispatch({ type: 'INSERT_INFO', json}); // 通过dispatch调用reducer
function* demoAction() {
yield* takeLastest('INSERT_INFO', axions.post(url: 'xxx', params));
}
}
Effect副作用函数
take
监听未来的action,他创建一个命令对象,告诉middleware等待一个特定的action,Generator会暂停,知道一个与pattern匹配的action被发起,才会继续执行下面的,take是一个阻塞的effect。(实际很少使用)
function* demoAction() {
while (true) {
yield take('WAIT_MOMENT');
yield fork(fetchData);
}
}
put
可以理解为redux中的dispatch函数,调用reducer方法中对应的方法,并且更新state
function* demoAction() {
yield put({ type: 'INSERT_INFO', data: list });
}
call
可以理解为调用其他函数的方法,一般通过call进行异步请求
function fetchData() {
axios.get(url, { data: { ...params } });
}
function* demoAction() {
const result = yield call(fetchData);
yield put({ type: 'UPDATE_DATA', data: { ...result });
}
fork
与call很类似,调用其他函数的,但是fork是非阻塞函数,执行完yield fork(fetchData)后,会立即执行后面的代码,而不是等待fetchData的返回结果。
function fetchData() {
axios.get(url, { data: { ...params } });
}
function* demoAction() {
const result = yield fork(fetchData);
}
select
只是middleware调用提供的选择器获取store中的数据。比如说我们要通过userid作为参数调用某个接口,这个时候我们可以不用通过结果再次获取,而是从之前就已经获取到并且存入到store中的user中获取
function* demoAction() {
const ID = yield select(state => state.user.id);
}
redux,react-redux,redux-saga这一整套下来还是很麻烦的,特别是在开发当中编写代码时,各种创建文件。建议大家有空可以看下dva框架,对这一整套进行了封装,更加利于理解。