LoginSignup
4
0

More than 1 year has passed since last update.

Django+Reactで学ぶプログラミング基礎(36): Reduxチュートリアル(MiddlewareでStoreをカスタマイズ)

Last updated at Posted at 2022-06-23
[前回] Django+Reactで学ぶプログラミング基礎(35): Reduxチュートリアル(TodoアプリのStoreをカスタマイズ)

はじめに

前回は、EnhancerとMiddlewareを用いてStoreをカスタマイズしました。
今回は、Middlewareの続きです。

今回の内容

Todoアプリの構築

  • カスタムMiddlewareの作成
  • Middlewareのユースケース

カスタムMiddlewareの作成

  • 独自のMiddlewareを作成し、特定動作をReduxアプリに追加
  • 下記Middlewareは、3つのネストされた関数として記述されている
    • 一番外側の関数exampleMiddlewareは、Middlewareそのもの
      • applyMiddlewareにより呼び出され、storeAPIオブジェクトを引数として受け取る
        • storeの{dispatch、getState}関数を含む
      • dispatch関数を呼び出すと、actionが送信され、Middlewareパイプラインが開始する
        • これは一度だけ呼び出される
    • 真ん中の関数wrapDispatchは、パイプラインのnextMiddleware
      • 引数としてnextを受け取る
      • next(action)を呼び出すと、パイプライン内のnextMiddlewareにactionが渡される
        • これも一度だけ呼び出される
      • このMiddlewareがシーケンスの最後のMiddlewareの場合
        • nextはオリジナルのstore.dispatch関数となる
    • 一番内側の関数handleActionは、actionがdispatchされるたびに呼び出される
      • 引数として現在のactionを受け取る
// Middleware written as ES5 functions

// Outer function:
function exampleMiddleware(storeAPI) {
  return function wrapDispatch(next) {
    return function handleAction(action) {
      // Do anything here: pass the action onwards with next(action),
      // or restart the pipeline with storeAPI.dispatch(action)
      // Can also use storeAPI.getState() here

      return next(action)
    }
  }
}
  • 上記Middlewareを、ES6のアロー関数を使用し、短く書ける
    • アロー関数にreturnステートメントが必要ない
const anotherExampleMiddleware = storeAPI => next => action => {
  // Do something in here, when each action is dispatched

  return next(action)
}

カスタムMiddlewareの例1: 更新後のstateをコンソール出力する

  • actionがdispatchされると、Middlewareパイプライの下記処理が走る
    • handleAction関数により、dispatchingメッセージがコンソール出力される
    • actionをnextセクションに渡す
      • nextセクションは、別のMiddleware、またはオリジナルのstore.dispatchとなる
      • 最終的に、reducerが実行され、stateが更新される
      • next関数が返される
    • storeAPI.getState()を呼び出し、新しいstateを確認
    • 最後に、nextMiddlewareから得られた結果値を返す
const loggerMiddleware = storeAPI => next => action => {
  console.log('dispatching', action)
  let result = next(action)
  console.log('next state', storeAPI.getState())
  return result
}
  • すべてのMiddlewareは任意の値を返すことができる
  • store.dispatch()を呼び出すと、最終的返却されるのはパイプラインの最初Middlewareの戻り値
    • 以下の例で、返却されるのはHello!
      • オリジナルstore.dispatchの結果ではない
const alwaysReturnHelloMiddleware = storeAPI => next => action {
  const originalResult = next(action);
  // Ignore the original result, return something else
  return 'Hello!'
}

const middlewareEnhancer = applyMiddleware(alwaysReturnHelloMiddleware)
const store = createStore(rootReducer, middlewareEnhancer)

const dispatchResult = store.dispatch({type: 'some/action'})
console.log(dispatchResult)
// log: 'Hello!'

カスタムMiddlewareの例2: 内部で非同期ロジックを実行

  • Middlewareはdispatchされた特定actionのみ処理可能
  • Middlewareは、内部で非同期ロジックを実行可能
    • 以下の例で、todos/todoAddedactionが発生したら
      • 1秒遅延後にaction.payloadをコンソール出力
const delayedMessageMiddleware = storeAPI => next => action => {
  if (action.type === 'todos/todoAdded') {
    setTimeout(() => {
      console.log('Added a new todo: ', action.payload)
    }, 1000)
  }

  return next(action)
}

Middlewareのユースケース

  • dispatchされたactionに対し、下記追加処理を実行

    • コンソールにログ出力
    • タイムアウトを設定
    • 非同期API呼び出し
    • acitonを変更
    • actionを一時停止するか、完全停止
  • Middlewareに、副作用のあるロジックを含められる

    • dispatchを変更し、プレーンでないオブジェクトをactionとして受け入れられる
      • プレーンでないオブジェクトとは
        • Class
        • Promise
        • function
        • その他組み込みJSタイプ
          • Map
          • Set Promise
          • Date

おわりに

Redux Middlewareを使用し、Storeをカスタマイズしました。
次回も続きます。お楽しみに。

[次回] Django+Reactで学ぶプログラミング基礎(37): Reduxチュートリアル(UIレイヤーのReactと統合)
4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0