みんな使ってる?React Queryで快適なAPI通信を実現しよう!
こんにちは、@nerusan_main です。
フロントエンド開発において、API 経由でデータを取得や送信するサービスは多いです。その時、axios や fetch 関数を利用して try/catch でデータを取得するかなって思います。例えば以下のようなソースコードです。
// データを取得する
const [data, setData] = useState({name: ''})
// このページに法問した時に一度だけ実行
React.useEffect(() => {
try {
(async () => {
// データを取得
const data = await axiod.get('https://endopoint.url');
// 正常系レスポンスの処理
// 取得データ尾をステートで管理
setData(data);
})();
} catch (err) {
// 取得に失敗すれば、例外をスローし、エラー内容に応じてユーザに通知する
}, [])
return (
<div>
<p>{data.name}</p>
</div>
);
また、取得する間は、ローディングをユーザに表示させることが望ましいですが、実装はなかなかめんどくさかったり、忘れたります。
また、ページを開くたびにリクエストを行うと、通信環境が悪い環境では、すぐデータが表示されず、ユーザにストレスを与えるサービスになりかねません。
そこで、便利なツールとしてreact-queryを紹介します。同じようなツールとして、swrがありますが、useQuery の方が機能が豊富であり、使いやすい印象があります。ですので、こんかいは、react-query を紹介します。
どんなことができるの?
以下のようなことができます。
- 宣言的に処理を記述でき、簡潔になり、ローディングとエラー表示が簡単
- キャッシュを利用して素早やくユーザに情報を表示できる
- Dev ツールが便利
以下、詳しく見ていきます。
宣言的に処理を記述でき、簡潔になり、ローディングとエラー表示が簡単
実際に取得の利用する useQuery を利用した例を見てみます。
const { isLoading, error, data, isFetching } = useQuery("repoData", () =>
axios.get(
"https://api.com"
).then((res) => res.data)
);
// ローディング中はローディングを表示
if (isLoading) return <Loding />;
// エラーならエラー表示
if (error) return <Error message={error.message} />
return (
<div>
<p>{data.name}</p>
</div>
);
どうでしょうか?ずいぶんスッキリし、わかりやすいコードになったのではないでしょうか?
useQuery では、ローディングフラグ、エラー、取得データを返却してくるので、それに沿って、ユーザに表示したい、コンポーネントを返してあげるだけで済みます。
このように記述できるのは、ローディング、エラー表示実装忘れを防ぐことができそうです。
キャッシュを利用して素早やくユーザに情報を表示できる
useQuery を利用することで、サーバからデータを取得するとデフォルトで 5 分間キャッシュに保存されます。(参照)。キャッシュ保存中であれば一度アンマウントしたコンポーネントを再度マウントするとキャッシュからデータを取得するので、すぐブラウザにデータを描写することができます。
つまり、一度訪れたページに、再度戻ってくる場合に、キャッシュデータを素早く表示してくれるので、ユーザはストレスなくブラウジングができます。
また、デフォルトでは、キャッシュを先に表示したあとすぐに、バックグランドでサーバーからデータをフェッチして、データの更新があればユーザに表示します。(この値はオプションの staleTime で変更可能。デフォルトでは0
なので、表示したあとすぐにフェッチする)
なので、古いデータじゃないかという心配もいりませんね!
詳しいオプションについてこちらをご覧ください。
dev tool が便利
react-query には、便利な dev ツールが用意されており、こちらが便利です。
具体的には、それぞれのリクエストなどのキャッシュ情報やステートの詳細を知ることができます。
ここのクエリは設定はどのようになっているんだろうっといった場合に、ここを見ると良いかもしれません。
POST、DELETE にも対応
また、取得の GET だけではなく POST や DELETE などにも対応しています。その時は、useMutation
を利用します。例えば、送信ボタンを押して、データを送信する場合などにも使えます。
ソースコード 0 は以下のようにします。
const mutation = useMutation((postData: {name: string}) => {
return axios.post('http://api.com/', postData)
})
return (
<div>
{mutation.isLoading ? (
'データ追加中'
) : (
<>
{mutation.isError ? (
<div>エラーがおきました: {mutation.error.message}</div>
) : null}
{mutation.isSuccess ? <div>追加が成功しました</div> : null}
<button
onClick={() => {
mutation.mutate({ name: "田中" })
}}
>
追加する
</button>
</>
)}
</div>
)
}
POST でも簡単にエラー表示、ローディング、成功時の処理が行えるのはとても便利ですね!
詳しい例題はこちら。
まとめ
以上、react-query についての簡単に説明しました。特に、クライアントサイドレンダリングを行う React の場合は、キャッシュを利用することでユーザに素早い表示を行えることができるので、UX が上がりそうです。
コードもスッキリし、可読性も上がり、ローディング処理、エラー処理も忘れずに行えそうなので、是非積極的に使っていきたいツールですね:)
参考
Discussion
わかりやすい記事