データ取得のための React Hooks ライブラリSWRの使い方
SWRとは
Next.jsを開発しているVercelによって提供されているReactベースのデータ取得のためのライブラリです。
下記の3つ点で便利かなと思います。
-
キャッシュを先に利用し、その後で最新のデータに更新するため、ユーザーに対してより速いレスポンスを提供できます。これにより、アプリケーションのパフォーマンスが向上します。
-
定期的にバックエンドにリクエストを送り、データが更新されていればそれを反映します。これにより、ユーザーにほぼリアルタイムのデータを提供することができます。
-
ローディング状態やエラー状態を簡単に扱えるフックを提供しているので、それらの状態を簡単に管理できます。
MSWとSWRを組み合わせたデータ取得について下記の記事で書いているので、この記事を読んでから見ていただくとイメージしやすいと思います。
インストール
下記コマンドでswrライブラリをインストールしてください。
npm install swr
使用例
フェッチしたいデータに対してuseSWR
フックを使用します。
下記の例では、/api/user
[1]からユーザー情報をフェッチしています。useSWR
フックは、データ(data)、ローディング状態、エラー情報を返します。これにより、コンポーネント内でデータのローディングやエラーハンドリングを簡単に実装できます。
import useSWR from 'swr'
export default function User() {
const fetcher = (url: string) => fetch(url).then(res => res.json());
const fetcher = (url: string) => axios.get(url).then((res) => res.data);
const { data: userData, error: userError, isValidating, mutate} = useSWR('/api/user', fetcher, {
revalidateOnFocus: false,
shouldRetryOnError: false,
revalidateOnMount: false,
})
if (userError) return <div>Failed to load</div>
if (!userData) return <div>Loading...</div>
return <div>Hello, {userData.name}!</div>
}
const { data: userData, error: userError, isValidating, mutate} = useSWR('/api/user', fetcher, { revalidateOnFocus: false, shouldRetryOnError: false, revalidateOnMount: false, })
の部分で、data: userData
としているのは、useSWR
から返されるdataオブジェクトにuserData
という新しい名前を割り当てているだけです。
返されるデータをそのままdataとして扱いたい場合は、以下のように記述してください。
const { data, error } = useSWR('/api/user', fetcher)
useSWR
useSWR
は、データをフェッチ(取得)し、ローカルのキャッシュに保存して自動的に再検証(更新)する機能を提供するSWRライブラリの一部です。
オプション設定
revalidateOnFocus
ページがフォーカスされた際に自動的に再検証を行うか設定できます。
shouldRetryOnError
エラーが発生した場合の再試行を行うか設定できます。
revalidateOnMount
コンポーネントがマウントされた際に再検証を行うか設定できます。
返り値
data
フェッチされたデータが含まれます。取得に成功した場合はデータがセットされ、失敗した場合は null になります。
error
フェッチ中またはフェッチ失敗時に発生したエラーが含まれます。
isValidating
現在データを再検証しているかどうかを示します。再検証中はtrue
になります。
mutate
データを再フェッチするための関数です。データを強制的に再取得したい場合に使用します。
axiosを使用して、POSTリクエストを送信する
await
を使用して、axios.post
とmutate
の非同期処理が成功したことを確認してから次のステップに進むように記述しています。
try/catch
ブロックを使用して、エラー時の処理を追加しています。
import axios from 'axios';
import { useRouter } from 'next/navigation';
import { mutate } from 'swr';
export default function Home() {
const router = useRouter();
const data = {
name: 'Mike',
age: 30,
occupation: 'engineer',
};
const nextOnClick = async () => {
try {
await axios.post<string>('/user', data);
await mutate('/user');
await router.push('/user');
} catch (error) {
console.error('An error occurred:', error);
}
};
return (
<main>
<button onClick={nextOnClick}>クリックして次へ</button>
</main>
);
}
fetchを使用して、POSTリクエストを送信する
先ほどのaxiosを使用する方法と比較すると、ヘッダーやリクエストボディを手動で設定する必要がありますが追加のライブラリを必要としません。
import { useRouter } from 'next/navigation';
import { mutate } from 'swr';
export default function Home() {
const router = useRouter();
const data = {
name: 'Mike',
age: 30,
occupation: 'engineer',
};
const nextOnClick = async () => {
try {
const response = await fetch('/user', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
if (!response.ok) {
throw new Error('Request failed');
}
await mutate('/user');
await router.push('/user');
} catch (error) {
console.error('An error occurred:', error);
}
};
return (
<main>
<button onClick={nextOnClick}>クリックして次へ</button>
</main>
);
}
mutate
mutate
関数を使うと、ウェブアプリケーションがサーバーから取得したデータを更新、再検証することができます。これは主に、データが変更された後にフロントエンドの表示をすぐに更新したい場合に役立ちます。
mutate
を使用する際は、通常GETリクエストで取得するデータのキャッシュを更新するために使います。
更新
ユーザーが何らかのアクション(例えば、プロフィール名の編集やコメントの投稿など)を行い、その変更をサーバーに送信した後、フロントエンドで表示されているデータを即座に新しい状態に更新します。
この時、実際にサーバーから新しいデータを取得する前に、フロントエンドの表示だけを先に更新することができます。これにより、ユーザーは自分の行った変更がすぐに反映されたように感じることができます。これはオプティミスティックUI[2]更新といいます。
再検証
更新後、あるいは任意のタイミングで、mutate
関数を使って特定のキーに対応するデータを再検証します。つまり、サーバーに再度問い合わせて最新のデータを取得し、フロントエンドの表示をサーバーのデータと同期させます。
このプロセスはバックグラウンドで自動的に行われるため、ユーザー体験に影響を与えることなく、アプリケーションのデータを常に最新の状態に保つことができます。
終わりに
何かありましたらお気軽にコメント等いただけると助かります。
ここまでお読みいただきありがとうございます🎉
Discussion