Day 29 middleware - thunk

第 29 天 !

剩~两~天~!

昨天已经把整个 redux 的流程给接起来了,

从 store 读取资料还有用 action 去改变 store , 这些我们大概都展示一次 ,

但是很多操作其实并不局限在本地端,

比较正确来说,

现在所做的一系列这样一步接一步的动作,我们称它为 sync(同步)

但总有一些操作是我们不会去等,直接前往下一步动作,但会先设定好操作结束後的相关动作,等它去触发,我们称它为 async(非同步)

redux 要处理 asyncactionreducer 都不能做这部份处理,

我们必须加入 middleware

redux 允许我们在这里处理 async 的相关操作,

那... middleware 会在什麽事後触发呢?

老样子, 这是官方提供的流程图

流程图

可以看到当我们的 action 去触发 dispatch 时候,在之前并不会直接进入 reducer , 而是会先进入 middleware 去跑一遍之後,再进去 reducer,

加入 middleware 後的流程应该是:

  • 执行 action
  • 触发 dispatch
  • 进入 middleware
  • 执行 async ,获取资料
  • 再次执行 action
  • 再次触发 dispatch
  • 进入 reducer 整理资料
  • 存入 store
  • 改变画面

那如何加入 middleware ?

第一先选择我们要使用的 middleware

就是我们今天要介绍的 redux-thunk

redux-thunk

先来安装:

yarn add redux-thunk

thunk 的内容很少,

function createThunkMiddleware(extraArgument) {
  return ({ dispatch, getState }) =>
    (next) =>
    (action) => {
      if (typeof action === 'function') {
        return action(dispatch, getState, extraArgument);
      }

      return next(action);
    };
}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;

export default thunk;

....嗯,这就是全部了,

有兴趣可以去 thunk 的 github 上看看,

它其实很简单的去建立了,在 middlewareasync 操作环境,

看程序码其实可以知道的是,middleware 提供了几个参数,

  • dispatch
  • getState
  • next
  • action
  • extraArgument

蛮直白的,

getState ,取得 store 的资料,

next ,代表是的这 action 直接往下一个 middleware 走,假如没有就进去 reducer

action , 当前发送的 action

extraArgument 这个是 thunk 2.0 才有的参数,主要一开始设定的时候可以带入额外的参数给 middleware

再来就是 thunk 只是很简单的去判断 action 送进来的是不是 function

是的话把 dispatch & getState & extraArgument 带入到这个 function

也就是说要做 sync 就照原样送 action ,

想要做 async 就把 action 用成 function,

再来就是把 thunk 塞入 redux 里,

使用 redux 提供的 applyMiddleware 来把 thunk 塞入 redux

import { applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducer';

export default function configureStore() {
  return createStore(rootReducer, applyMiddleware(thunk));
}

假如有需要额外塞资讯进去,

import { applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducer';

export default function configureStore(api) {
  return createStore(
    rootReducer,
    applyMiddleware(thunk).withExtraArgument({ api })
  );
}

这样 thunk 就进入到 redux 流程里了,

我们试着把 TodoList 的 新增用 thunk 实作

const fakeAsync = payload => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(payload);
    }, 3000);
  });
};

export const insertToDoThunk = payload => {
  return async dispatch => {
    const item = await fakeAsync(payload);
    dispatch(insertToDoAction(item));
  };
};

因为我们没有 api 所以设定一个 fakeAsync 来模拟 async,

那流程是 呼叫 insertToDoThunk 会延迟 3 秒,

之後让 dispatch 执行 insertToDoAction

Header componentinsertToDoAction 换成 insertToDoThunk

结果是:


<<:  [DAY29] 总回顾

>>:  人脸辨识-day29

Logback 配置来客制化 Log 讯息吧

在 Spring boot 可以使用 Logback 进行配置,系统预设加载日志配置档案 logba...

Day11|【Git】档案管理 - 重新命名档案 git mv

延续上篇的说明,在 Git 的世界,任何动作对 Git 来说都可以视为一个「修改」的动作。因此这篇要...

[Day 30] 完赛心得:你的前端之旅还尚未结束

未完待续的前端之旅 在这30天我们带到了前端技能树上各种类型的技能,包括基本的 HTML、CSS、J...

[Day12] [笔记]React Hooks - UseContent

前言 介绍 useContext 前,我们必须先认识 Context。 Context 概念有点像是...

「Android 必看」如何救回 WhatsApp 聊天记录?

WhatsApp 聊天记录消失了? 如何恢复 WhatsApp 照片和信息? 我们都有过 Whats...