Hydration error when using useQuery instead of useSuspenseQuery when prefetching

I have a page
export const PostsPage = async ({ params }: PostsPageProps) => {
trpc.posts.getAll.prefetch({ userId: user.id });

return (
<HydrateClient>
<PostsTable userId={user.id} />
</HydrateClient>
);
};
export const PostsPage = async ({ params }: PostsPageProps) => {
trpc.posts.getAll.prefetch({ userId: user.id });

return (
<HydrateClient>
<PostsTable userId={user.id} />
</HydrateClient>
);
};
and a component
export const PostsTable = ({ userId }: PostsTableProps) => {
const { data: posts, isPending } = trpc.posts.getAll.useQuery({
userId,
});

const { table } = useDataTable({
data: posts ?? [],
});

return (
<DataTable table={table} isLoading={isPending}>
{ /* ... */ }
</DataTable>
);
};
export const PostsTable = ({ userId }: PostsTableProps) => {
const { data: posts, isPending } = trpc.posts.getAll.useQuery({
userId,
});

const { table } = useDataTable({
data: posts ?? [],
});

return (
<DataTable table={table} isLoading={isPending}>
{ /* ... */ }
</DataTable>
);
};
Where the DataTable has some logic like
return isLoading ? (
<TableRow className="hover:bg-transparent">
{table.getLeafHeaders().map((_, i) => (
<TableCell key={i}>
<Skeleton className="h-6 w-full" />
</TableCell>
))}
</TableRow>
) : (
<TableRow>
<TableCell
colSpan={table.getAllColumns().length}
className="h-24 text-center"
>
No results.
</TableCell>
</TableRow>
)}
return isLoading ? (
<TableRow className="hover:bg-transparent">
{table.getLeafHeaders().map((_, i) => (
<TableCell key={i}>
<Skeleton className="h-6 w-full" />
</TableCell>
))}
</TableRow>
) : (
<TableRow>
<TableCell
colSpan={table.getAllColumns().length}
className="h-24 text-center"
>
No results.
</TableCell>
</TableRow>
)}
Using a useQuery in the PostsTable component results in a Hydration error. Can I prevent this without having to use Suspense? I found using the isPending flag to be a way simpler solution to rendering the skeleton in a deeply nested component.
5 Replies
Kaeon
Kaeon2mo ago
I'm having the exact same question, ever found a solution for this?
Brokenwind
Brokenwind4w ago
I updated to the latest and I seem to not be getting this anymore. Can anyone confirm?
Michael Schaufelberger
Nope, not yet unfortunately. Some findings: - If I delay the SSR after prefetching significantly (e.g. sleeping right after the prefetch for 4s so the prefetch can complete), the error goes away. This basically means, that if the promise is resolved already, it works. - If I delay the query's output significantly, so the prefetch cannot be done in time, the error goes away. - Everything else, is very prone to the hydration mismatch. I.e. it happens close to 100% of the time. Upgrading to the latest for the trpc and react-query packages did not work. As of now, that is:
"@tanstack/react-query": "^5.66.11",
"@tanstack/react-query-devtools": "^5.66.11",
"@trpc/client": "11.0.0-rc.819",
"@trpc/react-query": "11.0.0-rc.819",
"@trpc/server": "11.0.0-rc.819",
"@tanstack/react-query": "^5.66.11",
"@tanstack/react-query-devtools": "^5.66.11",
"@trpc/client": "11.0.0-rc.819",
"@trpc/react-query": "11.0.0-rc.819",
"@trpc/server": "11.0.0-rc.819",
Edit: This is the case if I use query.isFetching btw. I just need to use this, because I also want to change the table's behavior in case of a refetch. But this shouldn't matter for the initial render afaik.
Ed
Ed2w ago
I think we are having the same problem where we are consuming the pending state in a component that uses a prefetched query. The server renders with the isPending set to true. The client renders only when the data is loaded and therefore isPending is false. We render conditionally depending on this value so causes a hydration error.
Somebody
Somebody6d ago
is there a github issue for this yet? I couldn't find one. Tested on rc.833, server and client still have different states.

Did you find this page helpful?