LoginSignup
0
0

【React】SWRを便利に扱う自作メソッド

Last updated at Posted at 2024-02-11

はじめに

今回は、ReactでAPIのfetchを簡単に行えるSWRを、もうちょっと便利に扱う自作メソッド等をご紹介します。

「もっとこんなやり方があるよ!」等の意見がありましたら是非コメントにお願いします!🙇🏻‍♂️🙇🏻‍♂️

本題

もっとも基礎的・シンプルなSWRの使い方に、以下のようなコードがあります。
以下はユーザーのprofileデータをapiからfetchしてくるカスタムフックです。

const useProfile = () => {
    const headers = {
        "Content-Type": "application/json",
        Authorization: `Bearer ${localStorage.getItem("token")}`,
    };
    const url = `${API_URL}/profile`;

    const fetcher = async () => {
        return axios.get(url, { headers }).then((response) => {
            return response.data;
        });
    };

    const { data, error, isLoading } = useSWR<Profile>(url, fetcher);

    return { data, error, isLoading };
};

これでも十分にシンプルだとは思いますが、headersfetcherに関しては使い回しがかなり効くので切り出してしまいましょう。

例えば以下はそれらを切り出してみた例です。

const swrFetcher = async (url: string) => {
    const headers = {
        "Content-Type": "application/json",
        Authorization: `Bearer ${localStorage.getItem("token")}`,
    };

    const response = await axios.get(url, { headers });
    return response.data;
};

const useProfile = () => {
    const url = `${API_URL}/profile`;

    const { data, error, isLoading } = useSWR<Profile>(url, swrFetcher);

    return { data, error, isLoading };
};

こうしておけば、他のフックを作成する時にswrFetcherをimportして使用するだけなので、書くのが多少楽になります。

また、SWRにはデータの更新タイミング等を制御できる機能があります。
以下は、"初回のfetch以降、そのキャッシュを使い続ける"というoptionを付与したuseSWRです。
(useSWRImmutableという同等の機能を持つフックがありますが、説明のためuseSWRを使用します)

const useProfile = () => {
    const url = `${API_URL}/profile`;

    const { data, error, isLoading } = useSWR<Profile>(
        url,
        swrFetcher,
        {
            revalidateIfStale: false,
            revalidateOnFocus: false,
            revalidateOnReconnect: false,
        }
    );

    return { data, error, isLoading };
};

この時第三引数部分を切り出しておくと、コードが簡潔になり同じオプションを他で使いたい時便利になります。


const swrConfig = {
    // 初回のfetchのみ行い、以降はキャッシュを返すoption
    Immutable: {
        revalidateIfStale: false,
        revalidateOnFocus: false,
        revalidateOnReconnect: false,
    },
};

// 〜〜〜省略〜〜〜
    const { data, error, isLoading } = useSWR<Profile>(
        url,
        swrFetcher,
        swrConfig.Immutable
    );
// 〜〜〜省略〜〜〜

コメントを書いておけばどういったオプションなのか一瞥しただけでわかりますし、こうすることで再利用しやすくなります。

大変ためになるコメントをいただいたので、以下その内容を追記させていただきます。

ここまでの内容をまとめると、コードは以下の状態です。

const swrFetcher = async (url: string) => {
    const headers = {
        "Content-Type": "application/json",
        Authorization: `Bearer ${localStorage.getItem("token")}`,
    };

    const response = await axios.get(url, { headers });
    return response.data;
};

const useProfile = () => {
    const url = `${API_URL}/profile`;

    const { data, error, isLoading } = useSWR<Profile>(
        url,
        swrFetcher,
        swrConfig.Immutable
    );

    return { data, error, isLoading };
};

ここから更にコード量を減らし、楽に共通化できます。

axiosの機能にcreateというものがあります。
これはインスタンスを作成するメソッドで、使用することによりbaseURLheadersを変更したインスタンスを使用することができます。これを適用したコードは以下のようになります。

const instance = axios.create({
  baseURL: 'http://localhost:3003/api', // 先程までのAPI_URLにあたる部分
  headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${localStorage.getItem("token")}`,
    },
});

const swrFetcher = async (url: string) => {
    const response = await instance.get(url); // 上で作成したインスタンスを使用
    return response.data;
};

const useProfile = () => {
    const url = "profile";

    const { data, error, isLoading } = useSWR<Profile>(
        url,
        swrFetcher,
        swrConfig.Immutable
    );

    return { data, error, isLoading };
};

キーにも使用しているurlがかなりシンプルになり、swrFetcherも二行で済むものになりました。

同じくaxiosの、interceptors機能を使うことで同じような省略ができます。
これらは個人の好みや、やりたいことに対してどれだけ合っているかで選ぶ感じでしょうか。

おわりに

共通化できる部分はどんどん切り出していくとコードが見やすくなって良いんじゃないでしょうか🤗
SWRについて、またコードの書き方についてのコメント是非ともお願いします🙇🏻‍♂️

お読みいただきありがとうございました!

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0