zoukankan      html  css  js  c++  java
  • React从入门到放弃(4):Redux中间件

    redux 提供了类似后端 Express 的中间件概念。
    最适合扩展的是redux中的 store.dispatch 方法,中间件实际就是通过 override redux的store.dispatch() 完成
    将 action -> reducer 过程变为 action -> middlewares -> reducer 如:

    let next = store.dispatch;
    store.dispatch = function dispatchAndLog(action) {
      console.log('dispatching', action);
      next(action);
      console.log('next state', store.getState());
    }
    

    添加中间件

    redux提供了 applyMiddleware 方法便于添加中间件

    applyMiddleware的源码:

    export default function applyMiddleware(...middlewares) {
      middlewares = middlewares.slice()
      middlewares.reverse()
    
      // Transform dispatch function with each middleware.
      middlewares.forEach(middleware =>
        // 由于每次middle会直接返回返回函数,然后在这里赋值给store.dispatch,
        // 下一个middle在一开始的时候,就可以通过store.dispatch拿到上一个dispatch函数
        store.dispatch = middleware(store)
      )
    }
    

    通过middleware将 store.dispatch 进行扩展

    middleware会返回一个函数:return store => dispatch => action => {}

    异步操作

    1. 同步操作只要发出一种 Action 即可,异步操作通常需要发出多种 Action(开始、成功、失败)
    2. 异步操作有2种Action写法(3种type 或者 添加erro 和 response字段)
    3. 异步操作的state结构调整

    Action写法:

    // 写法一:名称相同,参数不同
    { type: 'FETCH_POSTS' }
    { type: 'FETCH_POSTS', status: 'error', error: 'Oops' }
    { type: 'FETCH_POSTS', status: 'success', response: { ... } }
    
    // 写法二:名称不同
    { type: 'FETCH_POSTS_REQUEST' }
    { type: 'FETCH_POSTS_FAILURE', error: 'Oops' }
    { type: 'FETCH_POSTS_SUCCESS', response: { ... } }
    

    异步State结构:

    let state = {
      // ...
      isFetching: true,// 正在获取数据
      didInvalidate: true,// 是否过期
      lastUpdated: 'xxxxxxx'// 上次更新时间
    };
    

    使用中间件

    1. 使用createStore(reducer, enhancer)createStore(reducer, preloadedState, enhancer)
    2. applyMiddleware的参数为中间件,某些中间件有顺序要求如:logger

    redux-logger

    redux-logger 可清晰记录 preState action nextState time等信息。

    示例:

    import { createStore, applyMiddleware } from 'redux'
    import createLogger from 'redux-logger'
    import rootReducer from './reducers'
    
    let store = createStore(rootReducer, applyMiddleware(createLogger));
    

    redux-thunk

    redux-thunk 用来优化redux中的异步操作。

    在store.dispatch 的方法参数只支持js对象(即Action),使用redux-thunk将支持参数为一个函数。

    或者说 redux-thunk 使得 action 从一个对象变成一个函数。

    函数签名:(dispatch, getState) => {}

    示例:

    import { createStore, applyMiddleware } from 'redux'
    import thunkMiddleware from 'redux-thunk'
    import rootReducer from './reducers'
    
    let store = createStore(rootReducer, applyMiddleware(thunkMiddleware));
    
    store.dispatch( dispatch => {
        dispatch({type:'CLICK_START',data:res})
        fetch('xx')
            .then(res => dispatch({type:'CLICK_END',data:res}));
    } )
    

    实际上,redux-thunk 的作用是让 Action Creator方便可以返回函数,这样让项目中的同步异步Action Creator调用可以保持一致

    redux-saga

    redux-saga 相比thunk 功能显得全面,精细。
    saga 是一个常驻进程,在复杂任务 及 长时事务场景非常适用。
    这里通过2个action 来展示 saga

    示例:

    import createSagaMiddleware, { delay } from 'redux-saga'
    import { all, put, takeEvery, takeLatest } from 'redux-saga/effects'
    
    function* helloSaga() {
        yield delay(1000)
        console.log('hello world')
    }
    
    function* incrementAsync() {
        yield delay(1000)
        yield put({ type: 'click' })
    }
    
    function* rootSaga() {
        yield all([
            takeEvery('hello', helloSaga),
            takeLatest('async', incrementAsync)
        ])
    }
    
    let sagaMiddleware = createSagaMiddleware();
    
    let store = createStore(rootReducer, applyMiddleware(sagaMiddleware))
    
    sagaMiddleware.run(rootSaga);
    
    store.dispatch({ type: 'hello' });
    store.dispatch({ type: 'async' });
    

    支持异步的还有redux-promise

  • 相关阅读:
    MAC OS系统替换homebrew使用阿里云的镜像源
    Javascript 交换两个变量的值
    Vue 中的 ref $refs
    Bluetooth M590 mouse problem Ubuntu
    Ubuntu 蓝牙鼠标的问题
    视频分享
    Vue项目中的文件/文件夹命名规范
    js打印div指定区域内容
    IntelliJ IDEA 配置
    idea安装
  • 原文地址:https://www.cnblogs.com/neverc/p/9071587.html
Copyright © 2011-2022 走看看