LoginSignup
6
8

More than 5 years have passed since last update.

ステップバイステップで Redux で非同期処理を行う React コンポーネントを作る

Last updated at Posted at 2016-08-26

概要

1日 Redux を触って既存のコンポーネントを書き換えていきました。サンプルやドキュメントはいきなり完成形のコンポーネントについて説明するものが多く分かりづらかったので、忘備録としてここにまとめます。

ステップバイステップで単純なコンポーネントから Redux で非同期処理を行うコンポーネントを作っていきます。

Redux のセットアップや store の作り方などは触れません。

1. Stateless Component を作る

固定の情報を表示するだけのものを作ります

HelloComponent.js
export default function HelloComponent(props) {
  return <p>Hello, {props.name}!</p>
}

HelloComponent.propTypes = {
  PropTypes.string.isRequired
}

2. Redux と接続する

一枚岩 state から必要な情報を加工して props に変換する mapStateToProps を追加します。

connect() に渡して Redux と接続されたコンポーネントを作ります。

HelloComponent.js
function HelloComponent(props) {
  return <p>Hello, {props.name}!</p>
}

HelloComponent.propTypes = {
  PropTypes.string.isRequired
}

// ログイン済みユーザーの情報 state.user からユーザー名を取り出して props.name に変換する
function mapStateToProps(state) {
  return {
    name: state.user && state.user.name
  }
}

export default connect(mapStateToProps)(HelloComponent)

3. イベントハンドリング

押した時にログアウトを行うボタンを追加します

Action を作成する

ログアウトする Action Creator を作ります。

  • アクションを識別する type の文字列
  • アクションを生成する関数 (Action Creator)
actions.js
export const SET_USER = "SET_USER"

// Action Creator
export function setUser(user) {
  return {
    type: SET_USER,
    user: user
  }
}

Action はこの Action Creator が返すオブジェクトのことです

Reducer を作成する

SET_USER に対応する state の遷移を実装します

reducers.js
import { combineReducers } from "redux"
import { SET_USER } from "./actions"

function user(state = null, action) {
  switch(action.type) {
    case SET_USER:
      return action.user
    default:
      return state
  }
}

export default combineReducers({
  user
})

Component 側の変更

ボタンを押した時に state.user を null にしてログアウトしたことにします。
onClick のようなイベントからアクションを生成する mapDispatchToProps を追加します。

HelloComponent.js
import { setUser } from "./actions"

function HelloComponent(props) {
  return <div>
    <p>Hello, {prop.name}!</p>
    <button onClick={props.onClickLogout}>Logout</button>
  </div>
}

HelloComponent.propTypes = {
  PropTypes.string.isRequired
}

function mapStateToProps(state) {
  return {
    name: state.user && state.user.name
  }
}

function mapDispatchToProps(dispatch) {
  return {
    onClickLogout: () => { dispatch(setUser(null)) }
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(HelloComponent)

4. 非同期処理

一番簡単だと思った redux-thunk ミドルウェアによる方法を説明します。

Action の変更

ログアウト API を叩き、成功時に setUser() で null をセットする非同期 Action を追加します。
非同期 Action は dispatch を引数にとる関数を返す関数として定義されます。

この関数は redux-thunk ミドルウェアが導入されていない場合エラーになります。

actions.js
export const SET_USER = "SET_USER"

// Action Creator
export function setUser(user) {
  return {
    type: SET_USER,
    user: user
  }
}

export const logout = () = dispatch => {
  exampleApi.logout(error => {
    if (!error) {
      dispatch(setUser(null))
    }
  })
}

コンポーネントの変更

setUser(null) を logout() に変えます。

HelloComponent.js
import { logout } from "./actions"

function HelloComponent(props) {
  return <div>
    <p>Hello, {prop.name}!</p>
    <button onClick={props.onClickLogout}>Logout</button>
  </div>
}

HelloComponent.propTypes = {
  PropTypes.string.isRequired
}

function mapStateToProps(state) {
  return {
    name: state.user && state.user.name
  }
}

function mapDispatchToProps(dispatch) {
  return {
    onClickLogout: () => { dispatch(logout()) }
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(HelloComponent)

所感

Redux を始めたばかりですが、思ったより地道に書き換える事ができてよかったです。非同期処理まわりはいろんな方法があるそうなので、規模に合わせていい感じの書き方を学んでいきたいと思います。

6
8
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
6
8