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

続きを読む

エンジニア独立

2019/4/15

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

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

続きを読む

エンジニア独立

2019/4/26

プログラマー・エンジニアが情報発信をするべき2つの理由

こんにちは。フリーエンジニアのてぃすです。 プログラマー・ITエンジニアとして働いている人が、SNSやブログで積極的に技術的なTipsや働き方に関する考え方を発信しているのをよく見ると思います。 情報発信をしたことのない人からすると、なんでそんな一銭の得にもならない行為をやっているのか、という疑問も湧いてくるでしょう。 知っている人は知っていることですが、エンジニアにとって情報発信ってすごいメリットがある行為なんです。 そこで今日はプログラマー・ITエンジニアが今すぐにでも情報発信を始めるべき2つの理由を ...

続きを読む

エンジニア独立

2019/4/29

技術を選んで働くエンジニアになるために

どうも、フリーランスエンジニアのてぃすです。 ITエンジニアと一言で言っても扱っている技術によって働き方は様々です。 また働き方に加えて、将来的なキャリアの展望も使う技術によって大きく変わってきます。 ぼくはエンジニアとして扱う技術を変化させていき、現在は週3でリモート中心でマイペースに働きながらゆとりを持って暮らせるくらいは稼げる程度にまで持っていけました。 そこで今回はITエンジニアが使う技術を選ぶことの大切さと、実際に選ぶためのテクニックについてご紹介していきます。 技術を選ぶ事による効能 まずは使 ...

続きを読む

エンジニア独立

2019/4/28

ITエンジニアが給与上げるために出来ることは限られている

どうも、フリーランスエンジニアのてぃすです。 今ITエンジニアってかなり稼げる職種として知られてきていますが、中にはその影響を感じられていない人もいるんじゃないかと思います。 ぼくは2年の間に正社員、派遣、フリーランスと渡り歩いて、月収は20万→40万→80万->100万と変動してきました。 その中でITエンジニアとして収入を上げるために出来ることがなんなのかが少しずつ見えてきました。 今回はその経験から感じたITエンジニアが収入を上げるために出来ることについて分析・解説していきます。 会社の中で給 ...

続きを読む

-プログラミング
-, ,

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