APIをクライアントと結合するときによくAxiosを利用します。
今回Axiosを利用するにあたって共通化できるものは無いか考えました。
コピペで使えますので是非活用してみてください。
インストール
axiosのインストールが済んでい場合は実行してください。
$ npm install axios
ディレクトリ構成
今回解説するディレクトリです。必要に応じて変更して下さい。
---src
|
|---component
| |---Apicomponent.tsx
|
|------api
| |---Api.tsx
|
|------screens
| |---App.tsx
|
|------Types
| |--Types.tsx
コンポーネント
コンポーネント部分を作っていきましょう。
AxiosRequestConfig
はinterface
を見ると分かります。必要に応じて追加しましょう。
import axios, { AxiosResponse, AxiosError, AxiosRequestConfig, AxiosInstance, Method } from 'axios'
const API_BASE_URL = 'http://localhost:xxxx' //繋ぎたいサーバに変更する
export const ApiComponent = async <T, R = AxiosResponse<T>>(
method: Method, // 必須項目。get,delete,post,putなど利用可能
url: string, //必須項目
data?: any, //BODY部分。送りたいデータを引数で渡す
headers?: Map<string, string>, //必要に応じて追加する
...requestConfig: any
): Promise<R> => {
const config: AxiosRequestConfig = {
...requestConfig,
baseURL: API_BASE_URL,
url: url,
method: method,
data,
timeout: 5000,
headers: {
'Content-Type': 'application/json',
Authorization: '',
...headers,
},
}
const axiosInstance: AxiosInstance = axios.create()
axiosInstance.interceptors.response.use(
(res: AxiosResponse<T>) => res,
//AxiosErrorはここで処理を行う
async (error: AxiosError) => {
console.error('error:', error)
if (error.response?.data) {
return error.response?.data
}
throw Error('AxiosError');
}
)
//ステータスコードによって処理を分岐可能にする
switch ((await axiosInstance.request(config)).status) {
//成功時はデータを返す
case 200: return (await axiosInstance.request(config)).data
//失敗時はエラーを出してあげる
default:
if (await axiosInstance.request(config) != null) {
const err: { message: string } | null | undefined = await axiosInstance.request(config)
if (err?.message) {
throw Error(err.message)
}
}
throw Error('UNHANDLED_ERROR');
}
}
Componentのコード解説
少しだけコード解説します。
今回利用しているのはinterceptor
です。
説明は割愛しますがAxiosの使い方は複数あります。
下記を参考にして頂くと分かりやすいと思います。
APIの成功時は、axiosInstance.request(config)).data
に必要なデータが格納されるようにカスタマイズしました。
AxiosError
AxiosErrorは何故必要なのか?
例えば、サーバに繋がらない時にAxiosError
が起きます。AxiosError
を指定すると通常では分からないエラーも確認出来るようになります。
AxiosErrorについてQiitaに記事投稿されていました。参考にしてみてください。
コンポーネント参考記事
参考にした上記コードは下記記事になります。少しだけ改良させていただきました。
APIを一元管理したい
次にAPIのpathを一元管理出来るようにやってみます。
APIのコンポーネントの引数は第一引数にmethodと第二引数のurlは必須です。
import { ApiComponent } from '../component/ApiComponent';
import { LoginData } from '../types/Types';
//第一引数と第二引数は必須
export function Api() {
return ApiComponent("get", "/")
}
//受け渡したいデータの型をコンポーネントの引数に渡すことも可能
export function LoginApi(loginData: LoginData) {
return ApiComponent("post", "/login", loginData)
}
//ユーザAPI URLを繋げて利用もOK
export function UserApi(userID: string, loginData: LoginData) {
return ApiComponent("post", "/user/" + userID ,loginData)
}
上記のやり方をすることで、APIの仕様が変わってもURLを変更するだけで済んだり、型の管理が分かりやすくなったと思います。
interface
interfaceの一例です。
//型の例
export interface LoginData {
userId: string
passWord: string
}
メインの処理コード
メインの処理コードです。必要に応じて変更して下さい。
import React, { useEffect, useState } from 'react';
import { LoginApi } from '../api/Api';
import { LoginData } from '../types/Types';
const App = () => {
const [loginData, setLoginData] = useState<LoginData>(
{
userId: "",
passWord: ""
}
);
const button = () => {
//API実行処理部分
//rejectは必要に応じて使ってください
new Promise((resolve, reject) => {
resolve(LoginApi(loginData)); //API実行
})
.then((res) => {
//成功処理を書く
console.log("resolve:", res)
})
.catch((res) => {
//失敗処理を書く
console.error("reject:", res)
//AxiosErrorが表示出来る。
if (res == "Error: AxiosError") {
if (res.data != null) {
console.error("AxiosError:", res.data)
} else {
console.error("AxiosError:", res)
}
return
}
console.error("Error:", res)
});
};
};
//---その他処理------//
APIの実行はresolve
に引数を指定してthenとcatchで処理を分岐させてみました。
他にも方法はありますので、メインの処理は必要に応じて変えてみて下さい。
Promise.resolve()については下記ページを参考にしてみてください。
最後に
Axiosについて少し詳しくなりました。エラーを一つ出すのもやり方があり、勉強になりました。
また、Axiosはキャンセル処理も出来たりします。コンポーネント部分はまだまだ改良出来そうですね。