概要
Redux / Flux の Action にはオブジェクトであれば何を指定しても大丈夫ですが、非公式のコーディング規約(flux-standard-action)があり、Redux の公式ドキュメントでもこのコーディング規約に従うことを奨励しています。
redux-actions
を使って、サンプルコードをコーディング規約に従った Action に修正します。
準備
Middleware編 の続き(tag/middleware)を使います。
Action の構造
flux-standard-action の規約では Action は次のような構造のオブジェクトになります。
{
type: FOO_TYPE, // must
payload: {object}, // optional
meta: {object}, // optional
error: false, true, undefined, null, ... // optional
}
type
には文字列またはシンボルで Action のタイプを設定します。
payload
にはデータを設定します。error
が true
の場合は Error
オブジェクトを設定します。
meta
には追加のデータを設定できます。
error
はエラーの状態を表します。(true
/ false
以外も指定できます)
redux の examples/real-world
のように従来は XXX_SUCCESS
XXX_FAILURE
のような type を定義していましたが、今後は error
を使って判定します。
簡単な例
RESET_ERROR_MESSAGE
が type
のみの Action なので、まずはこちらに redux-actions
を使います。
redux-actions
をインストールします。
npm i redux-actions --save
actions/index.js
を修正します。
import { createAction } from 'redux-actions'
export let resetErrorMessage = createAction(RESET_ERROR_MESSAGE);
/* オリジナル
export function resetErrorMessage() {
return {
type: RESET_ERROR_MESSAGE
};
*/
createAction
の第1引数に type
を指定すると ActionCreator が作成されます。
※ 名前は createAction
ですが、作られるのは ActionCreator です。
次にエラーメッセージの表示を修正します。
redux-actions
の問題点
今回のサンプルには、エラーメッセージを表示する機能があるため、action.error
を使いたかったのですが、機能が実装されておらず プルリクのマージ待ちです。
今回は meta
を使ってエラーを表現することにします。
payload
には空を、meta
には{error: {message: <message>}}
を設定する仕様にします。
import { createErrorMeta } from './error'
function empty() {
return {}
}
export let showErrorMessage = createAction(SHOW_ERROR_MESSAGE, empty, createErrorMeta);
/*
export function showErrorMessage(message) {
return {
type: SHOW_ERROR_MESSAGE,
error: message
}
}
*/
export function createErrorMeta(message) {
return {
error: {
message: message
}
}
}
createAction
の第2引数には payload creator を、第3引数には meta creator を指定します。
createAction
で生成した Action creator に指定した引数は payload creator / meta creator の両方に指定されます。
例えば、showErrorMessage
の場合、 showErrorMessage("test")
のように呼ぶと、empty
と createErrorMeta
の両方に "test"
が渡されます。
reducer
reducer は handleActions
を使って実装できます。
モーダルの表示部分で実装します。
export let showModal = createAction(SHOW_MODAL, (title, message) => ({title: title, message: message}));
export let hideModal = createAction(HIDE_MODAL);
import { handleActions } from 'redux-actions'
const messageModal = handleActions({
SHOW_MODAL: (state, action) => ({
visibility: "show",
title: action.payload.title,
message: action.payload.message
}),
HIDE_MODAL: (state, action) => ({
visibility: "hide"
})
}, messageModalInitial);
/*
function messageModal(state = messageModalInitial, action) {
const { type, title, message } = action;
switch (type) {
case ActionTypes.SHOW_MODAL:
return {
visibility: "show",
title: title,
message: message
};
case ActionTypes.HIDE_MODAL:
return {
visibility: "hide"
};
default:
return state;
}
}
*/
最後に
すべてを修正したものは tag/redux-actions です。
標準的なコーディング規約や手法にしたがっておくと、新しい人が参加するときに理解しやすくなります。
redux-actions
のようなライブラリは規約従ったコードを書けるだけでなく、ボイラープレートコードも減らしてくれるので、有効に活用していきたいです。