はじめに
redux-thunkをtypescriptで使っていた時に、typescript-fsa-rudx-thunkというパッケージが便利だったので紹介します。
非同期処理のactionを作るactionCreatorを提供しています。
typescript-fsaやredux-thunkの説明を詳しくすると長くなるので端折りながら。
typescript-fsaについて
Reduxの型定義をよしなにしてくれるパッケージはtypescript-fsaが有名。
import actionCreatorFactory from 'typescript-fsa';
const actionCreator = actionCreatorFactory();
//{foo: string}型がパラメータの型になる。
const somethingHappend = actionCreator<{foo: string}>('SOMETHING_HAPPENED');
console.log(somethigHappend({foo:"hoge"}));
// { type: 'SOMETHING_HAPPENED', payload: {foo:"hoge"})
payloadの型がactionCreatorのジェネリックスで指定した型になります。
型をactionCreatorを通して定義できます。
redux-thunkについて
redux-thunkはreduxで非同期処理を行う時に使用されるパッケージです。
redux-thunkを使わない場合
const somethingHappend = actionCreator<{foo: string}>('SOMETHING_HAPPENED');
fetch("http://example.com")
.then(response => response.text())
.then(text => {
store.dispatch(somthigHappend({foo:string});
});
redux-thunkを使った場合
const somethingHappend = actionCreator<{foo: string}>('SOMETHING_HAPPENED');
const asyncSomethingHappend = () => (dispatch: any) => any{
fetch("http://example.com")
.then(response => response.text())
.then(text => {
dispatch(somthigHappend({foo:string});
});
}
//asyncSomethingHappendはreduxのactionと同じようにdispatchできます。
store.dispatch(asyncSomethingHappend());
redux-thunkを使うと非同期処理を行う関数(thunkと呼ぶらしい)をdispatchできるようになりました。
非同期処理を行う関数(thunk)自体がactionとなるので、管理がしやすくなります。
typescript-fsa-redux-thunk
今までの説明では理解しやすくするために簡単な処理を書いていました。
しかし、私が実際に非同期処理をする時はいつも複雑になります。
通信が始まったときの処理だとか、終わったときの処理だとか、エラー時の処理だとか、
ただでさえ、reduxやredux-thunkを理解するのが大変なのに、、、
そこで、便利だったのがtypescript-fsa-redux-thunk。
非同期処理のaction(thunk)を作るactionCreaterを提供してくれています。
import actionCreatorFactory from 'typescript-fsa';
import { asyncFactory } from 'typescript-fsa-redux-thunk';
//ジェネリックスで渡しているStateはReduxのstoreのstateと同じ型です。
const createAsync = asyncFactory<State>(create);
interface LoginParams {
email: string;
password: string;
}
const login = createAsync<LoginParam,UserToken,CustomError>(
'Login',
// 引数で取っているparamsがLoginPramになります。
async(params,dispatch) => {
const res = await fetch("http://example.com/login",{
method: 'POST',
body: JSON.stringfy(params)
})
if(!res.ok) {
throw new CustomError();
}
//UserToken型を返します。
retrun res.json() as UserToken
}
);
const loginParam:LoginParam = {email:'hoge@example.om',password:'fuga'}
store.dispatch(login(loginParam));
//login.asyncの中
//{
// started: f LOGIN_STARTED
// done: f LOGIN_DONE
// failed: f LOGIN_FAILED
// type: 'LOGIN'
//}
createAsyncは非同期処理のaction(thunk)を作るactionCreaterになります。
createAsyncで作られたthunkはdispatchされると、
started:非同期処理が始まったとき
done:非同期処理が完了したとき
faild:非同期処理が失敗したとき
上記の三つのactionがdispatchされる。
これらの三つのactionはlogin.asyncの中に定義されている。
いちいち自分で記述しなくてよいので、楽です。
createAsyncの三つのジェネリックは順番に
1.createAsyncが作ったthunkの引数の型・createAsync第二引数の関数の第一引数
2.createAsyncの第2引数の返り値・doneアクションのparameter
3.エラーの型
になっている。
一番うれしいのが、started・done・faildのアクションを定義してくれていること。
最後に
説明難しい。