ユーザーアイコン

mizuko

3か月前

0
0

Next.jsのSSRで取得した値をTanStackQueryの仕組みで更新する

Next.js
TanStackQuery
ReactQuery

app/layout.tsなどのSSRコンポーネントで、prefetchQueryを行い、dehydrateをproviderに渡す。

export default async function RootLayout({ children, }: { children: React.ReactNode; }): Promise<JSX.Element> { let user: User | null = null; let userCategories: UserCategory[] = []; const accessToken = cookies().get('accessToken')?.value ?? ''; if (accessToken) { const [userData, categoriesData] = await Promise.all([ getMe(accessToken), getMeCategories(accessToken), ]); user = userData; userCategories = categoriesData; } const queryClient = new QueryClient(); await Promise.all([ queryClient.prefetchQuery({ queryKey: [GET_ME_KEY], queryFn: async () => await Promise.resolve(user), }), queryClient.prefetchQuery({ queryKey: [GET_ME_CATEGORIES_KEY], queryFn: async () => await Promise.resolve(userCategories), }), ]); return ( <html lang='ja'> <body> <Providers dehydratedState={dehydrate(queryClient)}> {children} </Providers> </body> </html> ); }

HydrationBoundaryにdehydrateを登録する。

export const Providers = ({ dehydratedState, children, }: ProvidersProps): JSX.Element => { const [client] = useState( new QueryClient({ defaultOptions: { queries: { staleTime: 5000, retry: false, refetchOnWindowFocus: false, }, mutations: { retry: false, }, }, }) ); return ( <QueryClientProvider client={client}> <HydrationBoundary state={dehydratedState}> <RecoilRoot> <ToastContainer /> <Suspense fallback={<LinearLoading />}>{children}</Suspense> </RecoilRoot> </HydrationBoundary> </QueryClientProvider> ); };

更新したいタイミングでinvalidateQueriesを行い再取得する。

export const usePostMeMemo = (): UseMutationResult< boolean, fetch.FetchError, PostMeMemoRequest > => { const queryClient = useQueryClient(); return useMutation<boolean, fetch.FetchError, PostMeMemoRequest>({ mutationFn: postMeMemo, onSuccess: () => { void queryClient.invalidateQueries({ queryKey: [GET_ME_MEMOS_KEY], }); void queryClient.invalidateQueries({ queryKey: [GET_ME_CATEGORIES_KEY], }); }, }); };