Recoil の Query Refresh Pattern を useRecoilRefresher_UNSTABLE に置き換える

以前作成したお天気アプリでは Recoil を使った Query Refresh Pattern を使用して、クエリのキャッシュを更新していましたが、 Recoil の 0.5.0 から実装されている useRecoilRefresher_UNSTABLE に置き換えてみました。
2021.12.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

MAD 事業部の高橋ゆうきです。

以前 Recoil でつくるお天気アプリ という記事で、Recoil の Query Refresh Pattern を紹介しました。

バージョン 0.5.0 からは、それを置き換えることができる useRecoilRefresher_UNSTABLE が実装されていたので、書き換えることにしてみました。

準備

以前使っていたリポジトリを再利用します。

まずはパッケージをまとめて更新してしまいましょう、ついでにバージョンも固定してしまいます。

yarn upgrade-interactive --latest

できた PR は以下になります。このまま yarn start を叩いても問題なく起動しました。

useRecoilRefresher_UNSTABLE

useRecoilRefresher_UNSTABLE が実装されたので、以前作成した useRefreshCityId を置き換えていきます。置き換えた結果は以下になります。

まずは Query Refresh Pattern の実装で使用した atomFamily を削除していきます。

都市の天気をリロードできるように変更 #1 の内容を revert してしまうのが早いです。

refresh するには useRecoilRefresher_UNSTABLE で戻される関数を実行するだけです。引数には RecoilValue をとるため weatherState を与えます。

import React, { useState } from "react";

import { useRecoilRefresher_UNSTABLE, useSetRecoilState } from "recoil";

import { cityIdState } from "../states/rootStates/cityId";
import { weatherState } from "../states/rootStates/weather";
import { cities, CityId } from "../utils/city";

export const WeatherForm: React.VFC = () => {
  const [cityId, setCityId] = useState<CityId>();
  const setStateCityId = useSetRecoilState(cityIdState);
  const refresh = useRecoilRefresher_UNSTABLE(weatherState);

  const changeCity = (e: React.ChangeEvent<HTMLSelectElement>) => {
    const id = e.currentTarget.value as CityId;
    setCityId(id);
  };
  const submit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    setStateCityId(cityId);
  };
  return (
    <form onSubmit={submit}>
      <select onChange={changeCity}>
        <option value="">選択なし</option>
        {cities.map((city) => (
          <option value={city.id} key={city.id}>
            {city.name}
          </option>
        ))}
      </select>
      <button type="submit">submit</button>
      <button onClick={() => refresh()}>refresh</button>
    </form>
  );
};

変更点は以上です。Query Refresh Pattern と比べると状態の更新のためだけに存在していた atomFamily が不要になっているため、かなりわかりやすくなりました。

Query Refresh Pattern

ここまで Query Refresh Pattern と書いてきましたが、現在のドキュメントでは Query Refresh Pattern の名称が消え、Use a Request ID と表記されています。

useRecoilRefresher_UNSTABLE はその関数名についている suffix を見ればわかるように、UNSTABLE であるため、従来どおり Use a Request ID を使って取得する選択肢が完全になくなったというわけではありません。

さいごに

Recoil を実際にプロジェクトで使ったことはないのですが、今の時点ですべての状態を Recoil で済ませるというのは若干厳しいものがあるかなという印象です(個人的な意見です)。

おおよそ 10 ヶ月ぶりに自分のコードを見たわけですが、とりわけやはり Query Refresh Pattern 部分はだいぶ理解に苦しむところがありました。今回は非常にシンプルなアプリですので問題になりませんでしたが、規模が大きいものであればこうはいかなかったかもしれません。

useRecoilRefresher_UNSTABLE はより使いやすくなる一歩なのですが、実際のプロジェクトで UNSTABLE な関数を使うというのもその要因の一つです。