React + Railsでのエラー周り実装の基本方針

タイトルの通り。そんな大した話ではないが今後の基本方針としてメモ。まぁ浅い内容。

動くコードは以下参照。

github.com

気にするべきエラーをひとまず以下の形で分類。

  • フロント: 入力値のValidation
  • フロント: APIレスポンス
  • API: サーバ側で発生する種々のエラー

以下詳細

フロント: 入力値のValidation

入力値のValidationはコンポーネントライブラリ(ant design)に任せる形をとる。 自分で実装する場合はValidation結果はなるべくコンポーネントローカルのstateにエラーの情報を持たせる方向を取りたい(reduxのstoreは使わない)

フロント: APIレスポンス

fetch等でAPIを叩いた結果、返ってきたレスポンスがエラーだった(4XX等)の場合の処理。 axiosであれば2XX以外は例外として処理されるので、catchして受け取ったエラーの中身をグローバルのstoreに反映させる。 反映結果を元に必要に応じてエラーメッセージを表示する

axiosでcatchする場合の注意点

axiosを使った場合、catchで受け取ったエラー情報は以下のようにerror.responseの形を取らないと参照できない。

axios.post('/test/create', this.formData)
  .then(response => { 
    console.log(response)
  })
  .catch(error => {
    console.log(error.response)
  });

async/awaitでエラー処理を書く際のパターン

以下の参考記事の通りいくつかパターンがあるので状況に応じて好きなものを使う。

qiita.com

個人的にお気に入りなのは、以下の「3. async function 内でエラーハンドリングしない」パターン。

const asyncFuncHandleErrorOut = async () => {
  const result = await errorPromise()
  console.log(result) // unreachable
}

// async function を呼ぶ時にエラーハンドリング
asyncFuncHandleErrorOut()
  .catch(err => console.log(err)) // Some error occured

成功時、失敗の処理をキッチリ分けられる & 個人的にtry-catchの形があまり好きでない という理由から推しの手法。

参考サイト:

[フロントエンド] axiosライブラリを使って、柔軟にHTTP通信を行う - YoheiM .NET
axiosのcatchでerror objectの中身を見れない - Qiita
Axios catch error returns javascript error not server response · Issue #960 · axios/axios · GitHub

API: サーバ側で発生する種々のエラー

サーバ側ではDBアクセスや外部サービスへのアクセス等、種々のエラーが発生し得る。発生し得るエラーの種類はとても書ききれないので以下記事参照。

qiita.com

エラー毎に対応するhttpステータスコードを設定してレスポンスを返す。エラー毎にどのステータスコードが適切か?などあまり理解していない。

参考サイト:

qiita.com morizyun.github.io

rescue_from

様々な箇所で共通で発生するようなエラー(例えば ActiveRecord::RecordNotFound など)は、rescue_fromを用いることで共通で処理できる。

参考サイト:

Rails tips: rescue_fromでコントローラのエラーをrescueする(翻訳)|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社
RailsのAPIサーバーのエラーレスポンスで例外に対応するエラーコードを返却する - Timee Product Team Blog

最後に

全体的にAPI(RESTful API)の設計周りの知識が明らかに不足している。今後以下の書籍を読んで基礎的な知識を固めて行きたいところ。

書評: RESTful Webサービス - t-wada の日記(旧)
Web API: The Good Parts | 水野 貴明 |本 | 通販 | Amazon