どうも、ぽっぽです。
GitHub – microsoft\frontend-bootcamp: Frontend Workshop from HTML\CSS\JS to TypeScript\React\Reduxを参考にRedux Thunkについて理解したことを紹介します。
基本的なRedux storeは同期的に更新します。Reduxでajaxなどによって非同期通信をするときはstoreをミドルウェアで拡張したthunkを利用します。
Redux Thunkミドルウェアはactionの代わりに関数を返すaction createrを使います。thunkはactionをdispatchするのを遅らせたり、ある条件のときだけdispatchするものです。返される内部の関数はdispatch
とgetState
を引数に持ちます。
Thunkとは何か
thunkとは式をラップしてその評価を遅らせる関数です。x
は評価された3が代入されます。foo
は評価されずに関数が代入されます。foo()
と呼び出して始めて評価されます。
let x = 1 + 2;
let foo = () => 1 + 2 ;
console.log('x is ' ,x,' foo is ',foo,' foo() is ', foo()); //x is 3 foo is () => 1 + 2 foo() is 3
thunkを使ったAction creator
action creatorは単にオブジェクトを返す関数です。
function addTodo(label: string) {
return { type: 'addTodo', id: uuid(), label };
}
サービスを呼ぶためのaction creatorは下記のようになります。
function addTodo(label: string) {
return async (dispatch: any, getState: () => Store) => {
const addAction = actions.addTodo(label);
const id = addAction.id;
dispatch(addAction);
await service.add(id, getState().todos[id]);
};
}
- 返される関数は引数に
dispatch
とgetState
を引数に指定します。 - 内部関数は
async
を有効にします。await
で非同期通信を実装します。 - 内部関数はstoreからのdispatch関数を通して追加のactionをdispatchする事ができます。
- 内部関数はまた
getState
によってstate treeにアクセスする事ができます。
具体的にaddTodo()
を実行する場合はこのようになります。
let foo = addTodo('foo'); // 関数を代入
foo(dispatch, getState); //内部関数を実行
プログラマーが実際に実装するのは、addTodo()
を実行するまでで、それ以降はthunkが処理します。
これにより、thunkミドルウェアにdispatch
するタイミングを丸投げするような格好になります。
Redux ThunkでTodoアプリを書いたソース
Reactで作成したTodoアプリにRedux Thunkを使ったソースをこちらからダウンロード出来ます。
このソースはCreate React App · Set up a modern web app by running one command.を使っています。複数のツールを組み合わせて必要な設定なども行ってくれているので便利でした。
npm install
npm start
Todoアプリを動作させる場合、NodeJSのコマンドプロンプトを開いて、ソースをダウンロードして展開した場所(package.json
ファイルがある)に移動します。1行目のコマンドを実行します。package.json
のパッケージをインストールして、インストールが終わるまで数十秒ほど待ちます。
2行目のコマンドを実行するとブラウザにTodoアプリが表示されます。
終わるときは、コマンドプロンプト上でCtrl + C
をタイプします。