177
157

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Redux 基礎:Action 編

Last updated at Posted at 2015-10-28

概要

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 がきちんと通るようにするまでが結構たいへんでした。
一度設定してしまえば、あまり変更しない部分なので自分用のテンプレートができると楽になると思います。

参考

177
157
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
177
157

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?