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/4/15

僕がITエンジニアとして独立しなかった場合の損失を計算してみた結果

どうも、フリーランスエンジニアのてぃすです。 僕はエンジニア歴が2年くらい経った頃に、月収が20万円を下回るような状態でした。 その後独立し、ほどなくして月収は100万円にまで到達しました。 実に5倍ほど収入が跳ね上がったことになります。 正直もう少し早く独立していればなぁと思っています。 今だからこそ考えられることですが、戦略さえしっかりしていれば、1年くらいは独立を早めることは可能だったと思うので。 こういう後悔というか振り返りをするたびに思うのですが、世の中僕以上に行動を遅らせることによる損失を食ら ...

続きを読む

エンジニア独立

2019/4/15

文系出身エンジニアが語る「弱いエンジニア」戦い方

こんにちは、フリーランスエンジニアのてぃすです。 僕は文系大学を卒業し、新卒で入ったITコンサル会社で入社半年後に軽くC#を扱う機会が訪れるまで、プログラミングやエンジニアリングに触れたことが一度もありませんでした。 パソコンも基本的に動画を見たりゲームをするための便利な箱くらいな印象。 一方、エンジニア業界には中学生時代から趣味でプログラミングをしてきたり、理系大学でバリバリ情報系を学んできたエンジニアがゴロゴロいるわけです。もう機械語で会話すればいいのにと思うレベルの猛者揃いです。 そうなると僕のよう ...

続きを読む

エンジニア入門

2018/1/2

プログラマになるために資格は必要か

ここ最近のエンジニア需要増大に伴って、プログラマやエンジニアになりたいと考え始める人が周りにも増えてきました。 そんな時によく聞かれるのが「プログラマになろうとしたら、資格とか取ったほうがいいの?」という内容。 確かに、真っ黒な画面に向かってカタカタ英語や記号を打ち込んでいるTHE 専門職であるプログラマという職業には、何かしら資格が必要に思えるかもしれません。 今日はそんなプログラマ・エンジニアを目指していて、最初の一歩として資格取得を検討している人に向けてプログラマになるのに資格が必要かという疑問に応 ...

続きを読む

エンジニア独立

2019/4/15

正社員エンジニアがフリーランスになるのは全く難しくないという事実

どうも、フリーランスエンジニアのてぃすです。 最近ではフリーランスエンジニアというのも珍しいものではなくなってきましたが、まだ誤解されている部分があります。 「フリーランスエンジニアになるのって大変なんでしょ?」 という誤解です。 エンジニアがフリーランスになるのに、 卓越した技術やセンス 業界内の幅広いコネ 仕事を取るための営業力 などは一切必要ありません。 今回はそのあたりの誤解を解消していきたいと思います。 フリーランス = ハイスキル ではない 世の中多くのエンジニアが誤解していることなんですが、 ...

続きを読む

エンジニア独立

2019/4/15

仕事を選べるITエンジニアになるための面談テクニック

どうも、フリーランスエンジニアのてぃすです。 ITエンジニアとして働いていく上で、大部分の人が経験する面談。 その後の数ヶ月、正社員や長期プロジェクトであれば数年の待遇を左右する超重要イベントなのですが、多くのエンジニアがこの重要性に気づいていません。 とりあえずこれまでの経歴を箇条書きして どこかで調べてきたような自己PRを適当に書いて 面談で書いてあることをそのまま口にする といった投げやりな面談を続けていては、売り手市場ということもあり仕事に困る可能性は低いですが、待遇の良い仕事を気づかないうちに逃 ...

続きを読む

-プログラミング
-, ,

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