やりたいこと
- Redux-sagaを使ってReactからRubyで作成したAPIに接続する
- Redux、Redux-sagaの使い方については下記記事参照
Reac初心者でも読めば必ずわかるReactのRedux講座 | アールエフェクト
redux-sagaとは何なのか? - Qiita
前提
- ruby: 2.7 + Rails: 6
- react: 16.8.6
ファイル構成
app
├── controller
│ └── forms_controller.rb
└── javascript
├── app
│ ├── containers
│ │ └── Form.js
│ └── redux
│ ├── actions
│ │ └── form.js
│ └── Saga
│ ├── api.js
│ └── index.js
└── utils
└── handleCallApi.js
処理手順
コンテナ
- 更新ボタンをクリックし、
submitForm
メソッドを呼び出す。引数にはフォームの入力値values
を渡す。 - 引数
values
を変数dataValues
に入れる。
※引数valuesはimmutableであるため別変数に入れて処理する必要がある。 - reduxのdispatch関数で
onFetchUpdateForm
メソッドを呼び出す。引数には変数dataValue
、正常終了後の処理、異常終了後の処理を渡す。app/javascript/app/containers/Form.jsimport React from 'react'; import { connect } from 'react-redux'; import { onFetchUpdateFormAction } from "../redux/actions/form"; import Button from '@material-ui/core/Button'; function Form(props) { // フォーム入力内容送信 const submitForm = values => { var dataValues = values props.onFetchUpdateForm({ data: dataValues, onSuccess: async data => { console.log("登録完了") // 正常終了後処理を以下記載 }, onError: error => { console.log("エラー発生") // 異常終了後処理を以下記載 } }) }; return ( <div> {/* フォーム部分省略 */} <Button onClick={submitForm}> 更新 </Button> </div> ); } // storeからデータ取得 const mapStateToProps = state => { return { formData: state.formData, }; }; // storeのデータ更新 const mapDispatchToProps = dispatch => { return { onFetchUpdateForm: data => { dispatch(onFetchUpdateFormAction(data)); } }; }; const FormInit = connect( mapStateToProps, mapDispatchToProps )(Form); export default FormInit;
action
-
onFetchUpdateFormAction
メソッドを呼び出すとき、「typeはON_FETCH_UPDATE_FORM
で処理する」と定義する。app/javascript/app/redux/actions/form.jsexport const onFetchUpdateFormAction = (data) => { return { type: "ON_FETCH_UPDATE_FORM", data } };
Saga
- typeが
ON_FETCH_UPDATE_FORM
の時、onFetchUpdateFormAction
メソッドを呼び出す。 - actionの
data
(フォームの入力値)を引数にputUpdateForm
メソッドを呼び出す。app/javascript/app/redux/Saga/index.jsimport {takeLatest} from 'redux-saga/effects'; import {Api} from './api'; function* onFetchUpdateFormAction(action) { const result = yield Api.putUpdateForm(action.data); } export function* watchOnFetchForm() { yield takeLatest("ON_FETCH_UPDATE_FORM", onFetchUpdateFormAction); }
-
takeEvery
とtakeLatest
の違いについては下記記事参照
【Redux】redux-sagaにおけるtakeEveryとtakeLatestの挙動確認 - Qiita
-
- urlにデータ更新処理を実行するURLを設定する。
-
callApi
メソッドを呼び出す。app/javascript/app/redux/Saga/api.jsimport callApi from "../../../utils/handleCallApi"; function* putUpdateForm(data) { const url = `http://localhost:3000/forms/${data.data.id}`; return yield callApi("put", url, data.data, data.onSuccess, data.onError); }
API接続
- AxiosによってAPIに接続する。引数には、
PUT
メソッド、接続するURL、タイムアウト時間、フォームの入力値を渡す。app/javascript/app/utils/handleCallApi.jsimport Axios from "axios"; import {csrfToken} from "@rails/ujs" export default function* callApi(method, url, data = null, onSuccess = null, onError = null) { Axios.defaults.headers.common['X-CSRF-Token'] = csrfToken(); try { const config = { method: method.toUpperCase(), url: url, timeout: 30000, data }; let response = false; response = yield Axios(config).then((response) => { onSuccess(response); return response; }, (error) => { onError(error); }); return response; } catch (error) { onError(error); return null; } }
-
csrfToken
については下記記事参照
Rails+React axiosで通信 ~CSRFトークンの設定~ - 開発メモメモブログ
-
- AxiosによってRailsのControllerが呼び出され、
update
メソッド内の処理が実行される。app/controller/forms_controller.rbclass FormsController < ApplicationController def update # 以下、更新処理記載 end end