SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

基礎からはじめるReact入門

Reduxで非同期処理を行う~Middlewareを使って実装する方法

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


今回の題材について~掲示板アプリの改修

 本記事では、第4回第7回で題材にした、掲示板アプリを改修していきます。これまでに作ってあった掲示板アプリは投稿内容をReactコンポーネントのstateに保持しており、あまり実践的なものではありませんでしたが、今回はサーバーとのやり取りを行う想定で作り変えるので、実践的な場面でも使える考え方になります。

改修の方針

 今回の改修には大きく分けて2つの目的があります。

  • 状態の管理をReactからReduxに移管する
  • 新しい投稿にIDを採番して保存する処理や、最新の投稿を取得してくる処理を、サーバーとやり取りする想定で非同期に記述する

 これらは従来、どちらもApp.jsが行っていた処理です。そのため、今回改修を行うReactコンポーネントはApp.jsのみで、Form.jsやList.jsは従来のものをそのまま使うことにします。リスト2は、これまで扱ってきた掲示板アプリのソースを含む、今回扱うファイルの一覧です。

[リスト2]今回扱うファイルの一覧
src/
  actions/
    posts.js (★)
  api/
    ApiClient.js (★)
  reducers/
    index.js (★)
    posts.js (★)
  App.css
  App.js (▲)
  Form.js
  index.js (▲)
  List.js

 ★マークがついているものは、今回のサンプルで新しく追加したものです。また、▲マークがついているものは、以前のサンプルから改修するものになります。

Reduxとやり取りできる形にコンポーネントを改修する

 まずは第8回で学んだ範囲でできることとして、App.jsをReduxに接続してみましょう。まだ作っていないAction CreatorやReducerの名前を使用しますが、これらは後から作っていくつもりで使う側から先に命名した方がうまくいくことがあるので、オススメの開発手法です。

 まずは、データの受け取り側としてconnect関数の適用を行います(リスト3)。

[リスト3]App.jsをReduxに接続する
class App extends Component {...}

function mapStateToProps(state) {
  return {
    postsState: state.posts // (1)
  }
}

export default connect(mapStateToProps)(App);

 前回の範囲なので詳しくは説明しませんが、(1)のように、掲示板アプリとして管理する状態にpostsという名前をつけてReducer側で管理し、AppコンポーネントにはpostsStateという名前のpropsを渡すことにしています。postsStateのPropTypes定義はリスト4の通りです。

[リスト4]postsStateのPropTypes定義
postsState: PropTypes.shape({
  posts: PropTypes.arrayOf(
    PropTypes.shape({
      name: PropTypes.string.isRequired,
      age: PropTypes.oneOf([
        Ages.TEEN,
        Ages.TWENTIES,
        Ages.THIRTIES,
        Ages.FOURTIES,
        Ages.FIFTIES,
      ]).isRequired,
      body: PropTypes.string.isRequired
    })
  ),
  error: PropTypes.bool.isRequired
}),

 これまで管理していた投稿データと同じ型のpostsとは別に、非同期処理でのエラーの有無を通知するためのerrorという真偽値型のプロパティも持たせています。今回は表示に使いませんが、こういった状態をReducer側で管理しておくと、エラー表示が簡単に行えるようになります。

 さて、このpropsに合わせて、render内のListコンポーネントへのデータ渡しをリスト5のように変更します。コンポーネントのstateから取り出していたpostsが、props由来のものに置き換わりました。

[リスト5]renderで表示する対象を変更する
<List
  posts={this.props.postsState.posts} />

 次に、初期化や新しい投稿の追加など、状態更新に関するところを変更します(リスト6)。

[リスト6]状態の更新を指示する箇所を変更する
import { initPosts, sendNewPost } from "./actions/posts";

class App extends Component {
  componentDidMount() {
    // 投稿を表示するための初期データをサーバーに請求する
    this.props.dispatch(initPosts()); // (2)
  }
  /** Formが作成した投稿を保存する処理 */
  saveNewPost(newPost) {
    // サーバーにデータを送る
    this.props.dispatch(sendNewPost(newPost)); // (1)
  }
  // 略
}

 Formコンポーネントから渡されてきたデータを処理する役割だったsaveNewPost関数のインターフェースはそのままに、内部実装だけを変更しました。投稿データはsendNewPostというAction Creatorで加工され、Reduxにスルーパスされます(1)。また、サーバー側にある既存のデータを表示したいので、新たにinitPostsというAction Creatorを作成しました(2)。

 さて、これでAppコンポーネントのRedux化が完了しました。propsでReducer管理下の状態を受け取って表示に使用し、Action Creator関数で作ったActionオブジェクトをdispatchして状態の更新を促すだけの、素直なRedux向けコンポーネントです。今見えている範囲における処理の流れをシーケンス図にすると、図5のようなものになります。

図5:画面を初期化する際のシーケンス図(ブラックボックスあり)
図5:画面を初期化する際のシーケンス図(ブラックボックスあり)

 まだ非同期処理の詳しいことを説明していないので、大きなブラックボックスがありますね。次節ではこのブラックボックス部分について具体的な実装を見ていきます。

次のページ
redux-thunkで非同期処理を実現する

この記事は参考になりましたか?

基礎からはじめるReact入門連載記事一覧

もっと読む

この記事の著者

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

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

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

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/10888 2018/07/05 11:37

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー