redux、react-redux、redux-saga看这就够了

276 阅读3分钟

Redux

官方解释--是js应用的可预测状态的容,可以理解为全局数据状态管理工具,用来组件通信和数据共享等功能。

使用场景:

  1. 某个组件的状态需要共享
  2. 某个状态需要在多个地方用到
  3. 一个组件需要改变其他组件的状态
  4. 一个组件需要改变全局状态

总体来说,在涉及到状态的共享时,如果通过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框架,对这一整套进行了封装,更加利于理解。