Edited at

Redux 基礎:Action 編

More than 3 years have passed since last update.


概要

React + Redux の Action についてサンプルを使って、Action の作成と動作の確認をします。


準備

redux/examples/real-world からいろいろそぎ落としたこちらのソースtag/init を使って説明します。

※ 実装完了はtag/action


Action とは

Action はストアの state を変更するためのメッセージです。

Action によって state が変わると UI の表示などアプリの変化が起きるので、アプリに何か起こすための出発点となります。


  1. Action 発行

  2. Reducer が現在の state と action を元に新しい state を作成。

  3. state の変更をUIなどに反映

Action は javascipt のオブジェクトでどのような形でも大丈夫ですが、慣習として type フィールドに文字列で Action のタイプを指定します。 type フィールド以外は自由に定義してください。



{

type: "SHOW_ERROR",
error: message
}


Action の作成

今回のサンプルには errorMessage という Reducer があります。


reducer/index.js

function errorMessage(state = null, action) {

const { type, error } = action;

if (type === ActionTypes.RESET_ERROR_MESSAGE) {
return null;
}

if (error) {
return error;
}

return state;
}


この Reducer は action.typeRESET_ERROR_MESSAGE のとき、新しい状態として null を返し、actionerror があるとき 新しい状態として error を返します。

アプリはこの状態を UI にエラーメッセージとして表示します。

この Reducer が処理できる Action を発行します。

まず、Action を発行するには ActionCreator を作ります。ActionCreator は Action を返すだけの単純な関数です。

actions/index.js にすでに resetErrorMessage という ActionCreator があるので同じように showErrorMessage を作ります。


actions/index.js

export const SHOW_ERROR_MESSAGE = 'SHOW_ERROR_MESSAGE';

export function showErrorMessage(message) {
return {
type: SHOW_ERROR_MESSAGE,
error: message
}
}



Action の発行

Action を発行するには、store.dipatch(action) に Action を渡しますが、react-redux の connect を使うと ActionCreator (と同じ形の function) で自動的に発行できます。

containers/App.js にすでに resetErrorMessage のコードがあるので、同じように connectshowErrorMessage を追加します。


containers/App.js

import { resetErrorMessage, showErrorMessage } from '../actions';

export default connect(mapStateToProps, {
resetErrorMessage,
showErrorMessage,
pushState
})(App);


connect が props に showErrorMessage (と同じ形の function)をマッピングするため、その function を呼んで発行します。


containers/App.js

  handleShowError(e) {

this.props.showErrorMessage("sample error!!");
e.preventDefault();
}

renderSample() {
return (
<ul>
<li><a href="#" onClick={::this.handleShowError}>show error</a></li>
</ul>
);
}


show error のリンクをクリックするとエラーメッセージが表示されます。 エラー表示後の Dissmiss をクリックするとエラーメッセージを消します。

右のペーンで Action と state の変化が確認できます。


bindActionCreators

Action を追加するたびに connect に追加するのはたいへんなので、bindActionCreators を使って自動的にマッピングします。

connect を次のように変更します。


containers/App.js

import { bindActionCreators } from 'redux';

// import { resetErrorMessage, showErrorMessage } from '../actions';  // 削除
import * as Actions from '../actions';

function mapDispatchToProps(dispatch) {
return {
...bindActionCreators(Actions, dispatch),
pushState
};
}

export default connect(mapStateToProps, mapDispatchToProps)(App);



非同期の Action

1秒後に何かしたいなど、非同期で Action を実行したい場合は、ActionCreator で function (dipatch) 型の function を返します。


actions/index.js


export function showErrorMessageDelayed(message, delay = 1000) {
return dispatch => {
setTimeout(() => {
dispatch(showErrorMessage(message));
}, delay);
};
}

さらに store に thunk という middleware を追加します。


store/configureStore.dev.js

import thunk from 'redux-thunk';

const finalCreateStore = compose(
applyMiddleware(thunk),
reduxReactRouter({ routes, createHistory }),
applyMiddleware(createLogger()),
DevTools.instrument()
)(createStore);


Action の発行や Reducer は特別な処理はなく同期型と同じです。


containers/App.js

  handleShowErrorDelayed(e) {

this.props.showErrorMessageDelayed("delayed sample error!!");
e.preventDefault();
}


最後に

サンプルで遊んでいるときは簡単だと思いましたが、Action がきちんと通るようにするまでが結構たいへんでした。

一度設定してしまえば、あまり変更しない部分なので自分用のテンプレートができると楽になると思います。


参考