CodeZine(コードジン)

特集ページ一覧

アプリの状態管理を安全に行うためのFluxとRedux

基礎からはじめるReact入門 第8回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2018/04/09 14:00
目次

ReduxでFluxなアプリを実装する(1)

 ReduxはFluxアーキテクチャを実現するためのライブラリのひとつです。Fluxで規定されている単方向データフローを実現しやすいようにDispatcherやStoreの仕組みを提供しているだけではなく、Store内のデータ管理をしやすくなる仕組みであるReducerや、機能を拡張するためのMiddlewareの仕組みが用意されていることが大きな特徴です。これらの概念を含めて図示したものが図3です。

図3 Reduxの概念図
図3 Reduxの概念図

 この図の中で最も重要なのはReducerです。Reducer自体は「Actionを受け取って、Actionの内容に見合った新しい状態を生み出して返却する」といった機能を持った関数です。StoreはReducerの単位で状態を管理しており、ReactなどのViewに状態を渡す際には、Reducerの単位で渡すのが基本になります。アプリケーションの中で発行されたActionは、すべてのReducerに渡されるので、Reducer側は自分が管理したいデータに関係のあるActionだけを見繕って処理・保存していくことになります。

 MiddlewareはActionが発行されてからReducerに渡されるまでに動く関数で、Actionを加工したり、副作用を起こしたり、なんでもアリの便利屋さんです。初心者のうちはMiddlewareを自作する機会はほぼないと思いますが、次回紹介する予定の「redux-thunk」など、有用なツールがMiddlewareの形で提供されていることが多いということは覚えておいてください。

サンプルの仕様について

 本稿ではReduxのサンプルとしてよく取り上げられる、カウンターアプリを作成します。

図4 カウンターアプリ
図4 カウンターアプリ

 カウンターアプリは次の3つの要素から構成されます。

  • カウント表示部
  • 「+1」ボタン
  • 「-1」ボタン

 「+1」ボタンを押すとカウント表示部の数字が加算され、「-1」ボタンを押すと減算される、というシンプルな仕様です。内部的には「現在のカウント数」という状態を扱うことになり、「+1」と「-1」にそれぞれ状態の増減を表すActionが割り当てられることになります。

Reduxをインストールする

 まずは、create-react-appで作成したプロジェクトにReduxをインストールします。次のコマンドを実行してください。

$ npm install --save redux
$ npm install --save react-redux

 reduxとreact-redux、ふたつのパッケージをインストールしました。ReduxはReactと相性の良いライブラリですが、Reactのためだけに作られたライブラリではありません。そのため、ReduxはReactと接続するための機能を持っていないのです。そんな事情から、Reactと併用する場合には、react-reduxをインストールする必要があります。

 package.jsonを開くと、dependenciesの中にreduxとreact-reduxが増えていることが確認できます。

リスト1 package.json
  "dependencies": {
    "react": "^16.0.0",
    "react-dom": "^16.0.0",
    "react-redux": "^5.0.7",
    "react-scripts": "1.0.16",
    "redux": "^3.7.2"
  },

カウンターアプリのUIを仮実装する

 Reduxの実装を始める前に、まずは一度、React側だけで動くサンプルを作ってみましょう。App.jsを次の通り実装します。

リスト2 src/App.js
import React, { Component } from 'react';

export default class App extends Component {
  /** コンストラクタ。stateの初期化もここで行います */
  constructor(props) {
    super(props);
    this.state = {
      count: 0 // (1)
    };
  }
  /** +1ボタンを押した際にstateを更新する処理 */
  _handlePlusOneClick(e) {
    this.setState({
      count: this.state.count + 1 // (2)
    });
  }
  /** -1ボタンを押した際にstateを更新する処理 */
  _handleMinusOneClick(e) {
    this.setState({
      count: this.state.count - 1 // (3)
    });
  }
  render() {
    const count = this.state.count;
    return (
      <div>
        <button onClick={e => this._handleMinusOneClick(e)}>-1</button> 
        <span>{count}</span> 
        <button onClick={e => this._handlePlusOneClick(e)}>+1</button>
      </div>
    );
  }
}

 この例では、(1)のようにAppコンポーネントのstateに状態(=カウント)を置いています。ユーザーが「-1」や「+1」のボタンを押した際には、(2)や(3)の通りsetStateで状態を増減させます。Reactだけでやりたかったことが実現できてしまいました。実は、この規模であればReduxがなくても実装できてしまうのです。

わざわざReduxを使う理由

 では、余計なツールを使わずにReactだけですべての状態管理をすればいいのか、というとそうではありません。実際に作るアプリには、ふたつどころではない多くのボタンが付いています。テキストを入力することもあるかもしれません。ボタンを押したのは何回目なのか、いま何文字入力しているのかを、状態として保持しなければいけないかもしれません。さまざまなユーザーイベントがコンポーネント内を飛び交い、それぞれのイベントに応じてどんな状態変更を行うのかを長々と記述することもあるでしょう。

 このようにアプリケーションの規模が大きくなっていくにつれて、Reactコンポーネントの見通しが悪くなっていきます。JavaScriptの中で手軽にレイアウトを構築できることがReactの大きな利点だったはずなのに、これでは本末転倒です。

 そういった状態管理を、ReduxのようなFluxアーキテクチャに切り出すことで、Reactコンポーネントが見た目の構築に注力できるのです。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:基礎からはじめるReact入門

もっと読む

著者プロフィール

  • WINGSプロジェクト 中川幸哉(ナカガワユキヤ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5