iT邦幫忙

2021 iThome 鐵人賽

DAY 29
0
Modern Web

React Native & Redux 初步探討系列 第 29

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

結果是:


上一篇
Day 28 加入 Action
下一篇
Day 30 完賽了...然後呢?
系列文
React Native & Redux 初步探討33

尚未有邦友留言

立即登入留言