TIS ENGINEER NOTE

ITエンジニアのためのキャリア向上ノウハウブログ

プログラミング

React + Reduxでサーバー通信ってどこでやればいいの?

更新日:

React + Reduxはその柔軟性から、Googleで調べて出てくる情報の一貫性がなく、機能を実装するときの調査が結構大変。

今回はリアルタイムチャットツールを開発したときの経験を元にReact + Reduxでサーバー通信を行うときの書き方について紹介していきます。

ちなみに今回の例ではRuby on RailsでAPIを構築し、そちらへ通信を行うという構成です。

使用するライブラリなど

サーバー通信用のライブラリ

javascriptでサーバー通信をするときに用いられるものとしてはajaxがメジャーですが、Reactで開発している中でajaxのためだけにjQueryを用いるというのはちょっとナンセンスです。

そこで今回はaxiosというサーバー通信用のライブラリを使用します。

Reactでサーバー通信する際は他にもsugaragentfetchが用いられることがありますが、書き方のわかりやすさ、名前のかっこよさから今回axiosをチョイスしました。

ただどのライブラリを使用するにしてもサーバー通信処理を記述する箇所に変わりはありません。

非同期処理用のミドルウェア

React + Redux構成において、stateを書きかえる処理はreducerに記載するのが基本です。しかし、そのstateを書き換えるという処理の都合上、reducerで行われる処理は同期処理でなければならず、ここに非同期のサーバー通信処理を行うことはできません。

そこでactionとreducerの間でサーバー通信を行えるようにするためのミドルウェアであるredux-thunkを導入します。

このミドルウェアを導入することによって、action creater上で関数の呼び出しが可能となります。

サーバー通信をどのタイミングで実装するかという決まりが存在していないため、今回は最もメジャーな手法であるこのaction-reducer間における非同期通信を実装していきます。

サーバー通信を行う為の最低限の構成

ミドルウェアの適用

storeを生成する際に読み込ませることでミドルウェアを実装することができます。

ここでのポイントはファイル構成にかかわらず、createStoreにapplyMiddlewareを使用してredux-trunkをstoreに読み込ませるというところです。

import { createStore, applyMiddleware } from 'redux';
import fromReducer from '../reducers/sample';
import thunkMiddleware from 'redux-thunk'

/* Storeの実装 */

export default function configureStore(){
  return createStore(
    fromReducer,applyMiddleware(thunkMiddleware)
  )
}

アクション

非同期のサーバー通信を実現するために必要なアクションは最低限以下の2つです。

  • 通信開始を伝えるアクション
  • 通信成功時にデータ更新を行うアクション

あとは失敗時に呼び出すアクションがあると便利ではありますが、今回は割愛します。

GETでデータ取得

まずはGETでサーバーからデータを取得するサーバー通信

前述したように、通信開始時、完了時にそれぞれアクションを呼び出しています。

完了時に呼び出されているアクションにおいて、取得したデータをstoreに渡すといったイメージです。

export const FETCH_MESSAGES = 'FETCH_MESSAGES'
export const FETCH_MESSAGES_SUCCESS = 'FETCH_MESSAGES_SUCCESS'

function requestMessages() {
  return {
    type: FETCH_MESSAGES
  }
}

function receiveMessages(json) {
  return {
    type: FETCH_MESSAGES_SUCCESS,
    messages: json
  }
}

// メッセージ取得
export function fetchMessages() {
  return dispatch => {
    dispatch(requestMessages())
    return axios.get('/messages.json').then((response) => {
        dispatch(receiveMessages(response.data))
      }).catch((response) => {
        console.log(response)
      })
  }
}

POSTでデータ送信

POSTでサーバー上のデータを更新する場合も記述箇所、基本的な記述内容は変わりません。

データ送信後、サーバーデータを取得することで現在の画面も最新に更新されます。

export const ADD_MESSAGE = 'ADD_MESSAGE'
export const ADD_MESSAGE_SUCCESS = 'ADD_MESSAGE_SUCCESS'

function addNewMessage() {
  return {
    type: ADD_MESSAGE,
  };
}
function addNewMessageSuccess() {
  return {
    type: ADD_MESSAGE_SUCCESS,
  };
}
// メッセージ送信
export function postMessage(messageBody) {
  return dispatch => {
    dispatch(addNewMessage())
    return axios.post('/messages.json',
    {
      body: messageBody
    },{withCredentials:true}
    ).then((response) => {
        dispatch(fetchMessages())
        dispatch(addNewMessageSuccess())
      }).catch((response) => {
        console.log(response)
      })
  }
}

Reducer

reducerについてはシンプルにサーバー通信用のフラグと取得した値を設定しておきます。

const initialState = {
  messages: [],
  isFetching: false,
};

export default function sample(state = initialState, action) {
  switch (action.type) {
    case 'FETCH_MESSAGES':
    return Object.assign({}, state, {
      isFetching: true
    });
    case 'FETCH_MESSAGES_SUCCESS':
    return Object.assign({}, state, {
      isFetching: false,
      messages: action.messages
    });

    case 'ADD_MESSAGE':
    return Object.assign({}, state, {
      isFetching: true
    });
    case 'ADD_MESSAGE_SUCCESS':
    return Object.assign({}, state, {
      isFetching: false,
    });

    default:
    return state;
  }
}

サーバー通信用メソッドの呼び出し

あとは実際にaxiosでサーバー通信を行っているメソッドを呼び出せばOKです。

GETの場合

データ取得の場合、初期表示についてはレンダリング後にfetchMessagesを呼び出せばstateが更新されます。

またデータ送信成功時にも同じ関数を呼び出しているため、データを追加したは自動的に追加された状態のデータが表示されます。

componentDidMount() {
  this.props.fetchMessages()
}

POSTの場合

フォームで入力した値をサーバーに送信する機能は以下の通りに作成したデータ送信用関数を呼び出せばOKです。

class FormInput extends React.Component {
  send(e) {
    e.preventDefault();
    this.props.postMessage(this.myInput.value);
    this.myInput.value = '';
    return;
  }
  render() {
    return (
      <form>
        <input type="text" ref={(ref) => (this.myInput = ref)} defaultValue="" />
        <button onClick={(event) => this.send(event)}>Send</button>
      </form>
    );
  }
}

まとめ

以上がRedux + Reactでの非同期サーバー通信の実装方法です。

「動かねえぞ!」って言う場合はお問い合わせなどいただければ、できる限り対応いたします。

閲覧いただき、ありがとうございました。

よく読まれている記事

エンジニア入門

2019/5/30

エンジニアにとっての理想的な職場とは

こんにちは、フリーランスエンジニアのてぃすです。 この記事を読んでくださっているということはITエンジニアかと思いますが、皆さんエンジニアとして働くならどんな環境で働きたいですか? スーツ勤務が嫌、言われたことをモクモクとこなすのが好き、など人によって理想として掲げる働き方って大きく異なります。 僕はこれまでエンジニアとして、SES企業やノリノリのベンチャー企業、起業したてのスタートアップ企業における業務を経験してきました。 今回は僕の経験や周囲のエンジニアから聞いた話を交えて、エンジニアにとっての働き方 ...

続きを読む

エンジニア独立

2019/5/29

エンジニアが会社員のままでいるのはヤバいなと感じた理由

現在会社員エンジニアからフリーランスエンジニアへの転身を目論んで活動中のてぃすです。 今回は僕が感じた会社に雇われた状態でエンジニアを続けることのデメリットについて語っていきます。 エンジニアは多くの現場で幅広い技術を習得するべきである 会社員としてエンジニアを続けることの最大のマイナスポイント。 それはキャリアのコントロールしにくいという点です。 エンジニアが携わるITの世界というのは、技術の流行り廃りが他の業界に比べて断トツで早いんですよね。 そうなるとその技術で生計を立てていくエンジニアという存在は ...

続きを読む

エンジニア独立

2018/1/28

手数料公開のエンジニア案件紹介サービス『Lancers Top』に登録してみた

日本最大のクラウドソーシングサービスであるランサーズを運営するランサーズ株式会社が今年の10月2日より開始したサービスであるLancers Top。 僕自身既に複数の案件紹介サービスに登録しているのですが、このLancers Topでは色々と面白そうな試みをしており、興味が湧いたため、登録して個人面談まで行ってきました。 今回は実際にLancers Topを利用してみての感想や他のフリーランスエージェントと比べたときの特色などについて紹介していこうと思います。 ランサーズとは? ランサーズといえば言わずと ...

続きを読む

エンジニア独立

2019/4/15

稼げないエンジニアは過小評価が原因

こんにちは、フリーエンジニアのてぃすです。 僕は正社員時代、3年目になっても手取りが20万にも届かない残念な状態にありました。その時は、 てぃすITエンジニアとか全然稼げない職業なんだな という印象を持っていました。別の業種に就こうと考えたことも1度や2度ではないです。 そして正社員を辞めてフリーランスになって月100万程度は安定して稼げるようになり、エンジニアの収入の相場のカラクリが少しずつ掴めてきました。 勘違いしないで欲しいのですが、単に正社員よりフリーランスの方が優れているということが言いたいわけ ...

続きを読む

エンジニア独立

2018/8/22

【厳選】現役フリーエンジニアが勧めるフリーランスエージェント2選

こんにちは、フリーエンジニアのてぃすです。 エンジニア、特にプログラマーがフリーランスになろうとしたとき、人脈豊富なスーパーエンジニアでもない限り、最も現実的な選択肢がフリーランスエージェントを利用した働き方です。 とはいえエンジニアバブルの昨今、そういったエージェントサービスは数多存在しており、戦国時代状態です。 選択肢が多いということは嬉しいことであり、同時にどれを選べばいいかという悩みにもなります。 各サイトではメリットや自サービスの長所しか書かれていません。当然ですが。 そうなると選ぶ側としては迷 ...

続きを読む

-プログラミング
-, ,

Copyright© TIS ENGINEER NOTE , 2019 All Rights Reserved Powered by AFFINGER5.