美文网首页react
到底什么是Redux中间件——基于Redux-thunk和Red

到底什么是Redux中间件——基于Redux-thunk和Red

作者: 雪燃归来 | 来源:发表于2020-06-21 00:26 被阅读0次

           前面的文章中,我们介绍过,React在发送Ajax等异步请求的时候,我们应该将异步请求的逻辑放在componentDidMount钩子函数中。但是有一个问题,当一个组件中有很多个异步请求操作,都放在这个钩子函数中,那么这个钩子函数会显得很臃肿,该怎么解决这个问题了? 在React中我们可以通过引入中间件的机制来解决这个问题。常用的中间件有redux-thunkdedux-saga

    一、Redux中的中间件

           首先,我们来看一下,Redux中的中间件是什么?如下图:

    Redux中的中间件
    React中的中间件位于ActionStore之间,中间件是对dispatch方法的封装和升级
           下面我们就以处理异步请求的操作来演示Redux中间件的使用方式。对于处理异步操作,我们常用的中间件有redux-thunkdedux-saga。至于两个中间件的差别,我们在具体讲解完这两个中间件后在进行说明。

    二、Redux中的中间件——Redux-chunk

           在之前文中《React数据管理工具Redux流程分析及基础使用实践》,我们在/src/store/actionCreators.js中定义action的时候,要求各函数最后返回的必须是一个对象,但是通过中间件redux-chunk的处理,可以允许actionCreators返回函数,我们可以在这个函数中执行我们的异步代码,执行完成之后返回对象。具体流程如下:
           1、安装Redux-chunk

    yarn add redux-thunk
    

           2、配置Redux-chunk环境
           /src/store/index.js

    import { createStore, applyMiddleware, compose } from 'redux'
    import thunk from 'redux-thunk'
    import reducer from './reducer'
    
    const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?   
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose
    
    const enhancer = composeEnhancers(
        applyMiddleware(thunk)
    )
    
    const store = createStore(reducer, enhancer)
    export default store
    

           此配置过程,可以查文档,也可以直接copy此处代码。
           3、设置返回值为函数的antion
           /src/store/actionCreators.js
           这块是redux-thunk的核心,也是我们最应该注意的地方。

    import { INIT_LIST_ACTION } from './actionTypes'
    
    export const initListAction = (data) => ({
        type: INIT_LIST_ACTION,
        data
    })
    
    export const getTodoList = () => {
        return (dispatch) => {
            setTimeout(function(){
                let data = ['learning react', 'learning redux'] 
                const action = initListAction(data)
                dispatch(action)
            })
        }
    }
    

           /src/store/actionTypes.js

    export const INIT_LIST_ACTION = 'init_list_action'
    

           4、在reducer中处理数据

    import { INIT_LIST_ACTION } from './actionTypes'
    export default (state = defaultState, action) => {
      ...
      if(action.type === INIT_LIST_ACTION){
            const newState = JSON.parse(JSON.stringify(state))
            newState.list = action.data
            return newState
        }
      ...
    }
    

           5、在组件中componentDidMount钩子函数中调用该异步请求
           /src/TodoList.js

    componentDidMount(){
            const action = getTodoList()
            store.dispatch(action)
        }
    

    三、Redux中的中间件——Redux-saga

           我们在使用Redux-thunk中间件的时候,是将异步的操作放在ActionCreators中的。而Redux-saga是将异步操作抽离到单独的文件中,通过调用generator函数执行。
           1、安装Redux-saga

    yarn add redux-thunk
    

           2、配置Redux-saga环境
    /src/store/index.js

    import { createStore, applyMiddleware, compose } from 'redux'
    import reducer from './reducer'
    import createSagaMiddleware from 'redux-saga'
    import todoSagas from './sagas'
    
    const sagaMiddleware = createSagaMiddleware()
    const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?   
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose
    const enhancer = composeEnhancers(
        applyMiddleware(sagaMiddleware)
    )
    const store = createStore(reducer, enhancer)
    sagaMiddleware.run(todoSagas)
    
    export default store
    

           3、创建saga文件

    import { takeEvery, put } from 'redux-saga/effects'
    import { GET_INIT_LIST } from './actionTypes'
    import { initListAction } from './actionCreator'
    
    function* getInitList(){
        try {
            const data = ['learning react','learning redux']
            const action = initListAction(data)
            yield put(action)
        } catch (e) {
            console.log('network error')
        }
    }
    
    function* mySaga(){
        yield takeEvery(GET_INIT_LIST, getInitList)
    }
    
    export default mySaga
    

           4、定义actionCreators中的action
    /src/store/actionCreators.js

    export const getInitList = (data) => ({
        type: GET_INIT_LIST
    })
    

           5、创建actionTypes类型

    export const GET_INIT_LIST = 'get_init_list'
    

           6、使用Redux-saga
    /src/TodoList.js

    import { getInitList } from './store/actionCreator'
    
    componentDidMount(){
        const action =  getInitList()
        store.dispatch(action)
    }
    

           使用Redux-saga,在组件中通过store.dispatch(action)提交action后,会在/src/store/sagas.js中的generator函数中监测到,我们在在sagas文件中完成我们的异步请求操作。在经过sagas处理之后,我们就可以在reducer中继续执行我们熟悉的操作了——修改数据。

    import { GET_INIT_LIST } from './actionTypes'
    
    export default (state = defaultState, action) => {
      ...
      if(action.type === GET_INIT_LIST){
            const newState = JSON.parse(JSON.stringify(state))
            newState.list = action.data
            return newState
      }
      ...
    }
    

           项目目录结构如下图:


    项目目录结构

           Redux-saga和Redux-thunk解决的问题一致,但是实现方式有所不同,saga把异步请求的操作全部放在saga文件中,而thunk只是来原来的基础上,对actionCreator进行一些操作(执行函数)。一般来说,saga用于大型复杂项目,其API很多,拓展性极好。

    相关文章

      网友评论

        本文标题:到底什么是Redux中间件——基于Redux-thunk和Red

        本文链接:https://www.haomeiwen.com/subject/gdggxktx.html