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.
8 Replies
Kaeon
Kaeon3mo ago
I'm having the exact same question, ever found a solution for this?
Brokenwind
Brokenwind2mo 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
Ed2mo 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
Somebody2mo 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.
Gabriel
Gabriel3w ago
This is happening to me
entropy
entropy3w ago
Can confirm I'm having a similar issue as well but it only happens every once in a while when I refresh. Here's a repo for reproduction: https://github.com/Entropy-10/hydration-failed-trpc-clerk
Ed
Ed3d ago
The fix for us to avoid the hydration error was to forcefully set isPending to true on the very first client-side render, which immediately gets reverted to use the one provided from the query.

Did you find this page helpful?