T
TanStack2y ago
fascinating-indigo

Query Invalidation with NextJS App Router + RSC

Hi there, running into a bit of a tricky situation with React-Query, Next.JS (App router), and server components. I have a feeling I'm using RSC + react-query incorrectly, so if this is just a dumb use case, feel free to let me know. I'm following a similar setup to the getQueryClient() example here: https://tanstack.com/query/latest/docs/react/guides/advanced-ssr
import { AscOrDesc } from "@/gql/graphql";
import { HydrationBoundary, dehydrate } from "@tanstack/react-query";
import { cookies } from "next/headers";
import getQueryClient from "@/queryClient";
import Scripts from "./scripts";
import { ScriptConnection } from "@/lib/queries/scriptConnection";

export default async function ScriptPage() {
const cookieStore = cookies();
const token = cookieStore.get("accessToken");

const queryClient = getQueryClient();

await queryClient.prefetchQuery({
queryKey: [
"getScripts",
{
cursor: "",
searchTerm: "",
filters: [],
limit: 10,
sortBy: "id",
sortDir: AscOrDesc.Asc,
accessToken: token?.value || "",
},
],
queryFn: ScriptConnection,
});

return (
<HydrationBoundary state={dehydrate(queryClient)}>
<Scripts />
</HydrationBoundary>
);
}
import { AscOrDesc } from "@/gql/graphql";
import { HydrationBoundary, dehydrate } from "@tanstack/react-query";
import { cookies } from "next/headers";
import getQueryClient from "@/queryClient";
import Scripts from "./scripts";
import { ScriptConnection } from "@/lib/queries/scriptConnection";

export default async function ScriptPage() {
const cookieStore = cookies();
const token = cookieStore.get("accessToken");

const queryClient = getQueryClient();

await queryClient.prefetchQuery({
queryKey: [
"getScripts",
{
cursor: "",
searchTerm: "",
filters: [],
limit: 10,
sortBy: "id",
sortDir: AscOrDesc.Asc,
accessToken: token?.value || "",
},
],
queryFn: ScriptConnection,
});

return (
<HydrationBoundary state={dehydrate(queryClient)}>
<Scripts />
</HydrationBoundary>
);
}
I am calling both useQuery and useMutation from nested client components, and everything seems to be working fine(?). The issue I'm running into is with query invalidation. My goal is that on a mutation, the necessary changes are re-fetched and rendered.
// inside of a client component
const queryClient = new QueryClient()

const updateScript = useMutation({
mutationKey: ["updateScript"],
mutationFn: UpdateScript,
onMutate: () => {
// in react-query dev tools, getScripts is never invalidated
queryClient.invalidateQueries("getScripts");
...
...
// inside of a client component
const queryClient = new QueryClient()

const updateScript = useMutation({
mutationKey: ["updateScript"],
mutationFn: UpdateScript,
onMutate: () => {
// in react-query dev tools, getScripts is never invalidated
queryClient.invalidateQueries("getScripts");
...
...
If I'm in a client component, and try to invalidate a query, nothing happens. I've tried using both new QueryClient() and getQueryClient() , as well as making a Next.JS route handler (API endpoint) to invalidate the server singleton QueryClient query. Is it even possible to invalidate queries from the clientside (when prefetching from the server), or am I just using react-query incorrectly? I have confirmed the query keys match, it's just that the query never seems to be marked as stale. Thanks. Let me know if more examples are necessary.
Advanced Server Rendering | TanStack Query Docs
Welcome to the Advanced Server Rendering guide, where you will learn all about using React Query with streaming, Server Components and the Next.js app router. You might want to read the Server Rendering & Hydration guide before this one as it teaches the basics for using React Query with SSR, and Performance & Request Waterfalls as well as Pre...
2 Replies
genetic-orange
genetic-orange2y ago
You need useQueryClient()
fascinating-indigo
fascinating-indigoOP2y ago
🤦🏻‍♂️that’s definitely it. Thanks, will give it a test shortly Yeah that was the issue. Appreciate it 🙏

Did you find this page helpful?