Closed2
React Query、内部処理の結果をキャッシュするメモ
TanStack Queryをメインで用いるとき、主には以下のユースケースになる。
- 基本的にはuseQueryを使って外部APIを呼び出し、得られたデータをキャッシュする。
- キャッシュの有効期限を制御する(cacheTime)
- この時間が経つまで、事前に取得したデータのキャッシュを利用できる。この時間を超えていたら、データ取得+キャッシュの更新を行う
- Stale-While-Revalidateを行う(staleTime)
- 前回のデータ取得からstaleTime経過していたら、アクセス直後からバックグラウンドでデータ取得を行う(このとき、キャッシュが有効であればキャッシュをそのまま返す。取得したデータがキャッシュから使えるようになるのは次のアクセス時)
- データの更新・削除を行う際、useMutationを使う
- 処理が成功していたら、キャッシュを無効化する。データの更新・削除に伴い、キャッシュが古くなっているため。
- キャッシュはQueryKeyによって管理される。
- e.g. ["todos"]、["todos", "1"]、["todos", "1", "subtodos"]、["todos", "1", "subtodos", "a"]
- 以前はstringを入れられていたが、v4時点ではarrayでないとNG。
- e.g. ["todos"]、["todos", "1"]、["todos", "1", "subtodos"]、["todos", "1", "subtodos", "a"]
TanStack Queryを状態管理として使うとしたとき、非同期な内部処理を実行し、結果を保存しておきたいことがある。
この場合、例えば以下の様にカスタムクエリを作ることができる。ここでは、何らかのパラメータに基づいて数値シミュレーションを行い、その結果をキャッシュすることを想定している。
const CACHE_KEY = ["SimulationResult"];
export const useMathematicalSimulation = (): {
simulationResult: SimulationResult; // SimulationParams含め、型は適宜定義すること
error: Error | null;
isLoading: boolean;
runSimulation: (params: SimulationParams) => void;
} => {
const queryClient = useQueryClient(); // App.tsxなどで、<QueryClientProvider>の追加が必要
const getInitialResult = () => null; // cacheTime = infinityなので、useQueryの初回実行時しか呼ばれない。useQueryではqueryFnが必須なので便宜的に定義している
const { data, error, isLoading } = useQuery<SimulationResult, Error>(CACHE_KEY, getInitialResult, {
initialData: null, // simulationResultの型をNonNullに保つために必要
cacheTime: Infinity, // runSimulationを呼ばない限り、キャッシュを残したい
staleTime: Infinity, // キャッシュを自動で無効化する必要はない
});
const update = async (params: SimulationParams): Promise<SimulationResult> => {
/* 内部処理をここで行う。以下のsimulationResultは内部処理の結果の想定 */
return simulationResult;
};
const { mutate } = useMutation((params: SimulationParams) => update(params), {
onSuccess: (simulationResult) => {
queryClient.setQueryData(CACHE_KEY, simulationResult);
},
onError: (err) => {
/* 内部処理が失敗したときの処理を必要に応じ書く */
},
});
return { simulationResult: data, error, isLoading, runSimulation: mutate };
};
あとはcomponent側で、以下の様に呼び出して使う。
const SimulationPage: (props: Props) => JSX.Element = () => {
const { simulationResult, isLoading, error, runSimulation } = useMathematicalSimulation();
return (
<div>
{isLoading && (/* ローディング時の表示 */)}
{error && (/* エラーがあるときの表示 */)}
...
<SomeComponent onSubmit={(params) => runSimulation(params)} />
...
</div>
);
}
このスクラップは2022/11/13にクローズされました