redux-actionsを使うと、Flux Standard Action(FSA)に則ったAction
を簡単に作れる。
が、エラーがあったときのAtionはどう作ればよいのだろう。
よく読めば公式に書いてあるのだが、直接的なコードはなかったのでメモ。
- createAction(s) | API Reference | redux-actions
TL;DR
- FSAはActionの型を定義している。
createAction(type, payloadCreator)
は通常自動的に{type=FOO, payload=returnValue}
なオブジェクトを返すpayloadCreater
がError
を返したときは自動的に{type=FOO, payload=Error, error=true}
なオブジェクトを返す
// 通常は{type="READ_EVENTS", payload=response.data}なActionが生成される。
// 例外発生時は{type="READ_EVENTS", payload=Error, error=true}なActionが生成される。
export const readEvents = createAction("READ_EVENTS", () =>
axios.get(`${RESOURCE_URL}`).then(response => {
return response.data;
})
);
動作する文中のサンプルコードのプロジェクトは以下になる。
利用するredux-actionsのバージョンは2.6.1。各ライブラリのバージョンの詳細は以下のファイルを参照のこと。
FSA準拠のアクションを作る
Flux Standard ActionはReact + Redux(Flux)で利用するActionの形を定めている。
- Actions | Flux Standard Action
Flowtypeの記法で型を書くと、Action
は以下のような型になる。
export type ActionT<A: Action, P> = {|
type: A,
payload?: P | Error,
error?: boolean,
meta?: mixed
|};
プロパティ名 | 意味 |
---|---|
type | Actionを識別する一意な文字列 |
payload | ロジックの結果、もしくはError 。Optional |
error | 処理が失敗した場合true を返す真偽値。Optional |
meta | ロジックの結果には無関係なデータ。Optional |
redux-actionsのcreateActionでActionを作る
Redux利用時はredux-actionsのcreateAction(type, payloadCreator)
を使うと、このAction
を簡単に作れる。
第一引数にtype
に相当する情報、第二引数にはpayload
に入れる情報を返す関数を渡す(引数が2つでないcreateAction
もある)。
redux-promise
などと組み合わせると非同期処理も含めることができる。
-
redux-actions
-
createAction(s) | API Reference | redux-actions
import axios from 'axios';
import { createAction } from 'redux-actions';
export type ReadEventsAction = {
type: typeof ReadEvents,
payload?: EventMap | Error,
error?: boolean
};
// 通常は{type="READ_EVENTS", payload=response.data}なActionが生成される。
// 例外発生時は{type="READ_EVENTS", payload=Error, error=true}なActionが生成される。
export const readEvents: void => ReadEventsAction = createAction("READ_EVENTS", () =>
axios.get(`${RESOURCE_URL}`).then(response => {
return response.data;
})
);
createActionで{type=FOO, payload=Error, error=true}なオブジェクトを返す
上記のサンプルコードのコメントに書いたが、内部でエラーが発生すれば自動的にAction
のなかのerror
がtrue
になる。
reducer
の中で使えるhandleAction
関数も用意されているので、error = true
のときの処理をthrow
に書けばよい。
import { handleActions, type ActionType } from 'redux-actions';
const initialState: {
events: EventMap | {}
} = { events: {} };
export default handleActions(
{
["READ_EVENTS"]: {
// Actionが正常に完了したときの処理
next(state: { events: EventMap | {} }, action: ActionType<typeof readEvents>) {
console.log(action);
return { ...state, events: action.payload };
},
// Actionが異常終了したときの処理
throw(state: { events: EventMap | {} }, action: ActionType<typeof readEvents>) {
// エラー処理など
return { ...state, events: {} };
}
}
},
initialState
);
最後に
“redux-actions
を使えばいい感じに処理してくれる"のを期待して使ってみたが、ここまでもろもろ処理してくれると思っていなかった。
ずっと「createAction
はpayload
の値は操作できるけど、error
をtrue
にするにはどうするんだろう?」とハマっていた。
ちゃんとドキュメントを読んでいなかったのが原因。とは言え、以下のように書いてあってもなんかピンと来ない気がする。
- createAction(type, payloadCreator)
NOTE: If payload is an instance of an Error object, payloadCreator will not be called.
payloadCreator
を呼ばないとpayload
インスタンスはわからないと思うのだが…createAction(type)
の説明から続いているのだろうか。
- createAction(type)
If the payload is an instance of an Error object, redux-actions will automatically set action.error to true.
こっちの一文はわかりやすい。
参考
- Flux Standard Action(FSA)
- redux-actions
- createAction(s) | API Reference | redux-actions
- createAction.js