Description
Describe the bug
In a Next.js 14 app directory project with React Query 5 inside a client component, if I use reference (queryFn: getProjects
) for the query function instead of an inline function that calls a function, I get this error:
Only plain objects, and a few built-ins, can be passed to Server Actions. Classes or null prototypes are not supported.
Doing it this way works:
useQuery({
queryKey: ['projects'],
queryFn: () => getProjects(),
});
Is this a bug?
I understand what a plain object is, and getProjects does return a promise to a serialisable object.
Your minimal, reproducible example
https://codesandbox.io/p/sandbox/gracious-golick-fq3ss9
Steps to reproduce
My useQuery
call is abstracted away inside a custom hook that starts with 'use client';
:
'use client';
import { useQuery } from '@tanstack/react-query';
import { getProjects } from '@/db/queries';
export default function useProjects() {
return useQuery({
queryKey: ['projects'],
// works if inline function not if 'queryFn: getProjects'
queryFn: () => getProjects(),
});
}
This hook is used in a client component ('use client';
). The error also happens if I use useQuery
directly in the client component and skip the custom hook.
getProjects
comes from a file prefixed with 'use server';
(the query is run by Drizzle on Turso):
'use server';
import 'server-only';
import { db } from '@/db/';
import { projects } from '@/db/schema';
export const getProjects = async () => db.select().from(projects);
I use the HydrationBoundary pattern, but even if I remove that from page.tsx
and just create a client side query client, I get the same error too, unless I use an inline query function.
Expected behavior
useQuery
accepts both a function reference and an inline function for queryFn
.
How often does this bug happen?
Every time
Screenshots or Videos
No response
Platform
- OS: macOS
- Browser: Chrome
- Version: 118.0.5993.117
Tanstack Query adapter
react-query
TanStack Query version
v5.4.3
TypeScript version
v5.2.2
Additional context
The error only kicks in after a few seconds, so it looks like React Query is doing it's default attempt at trying a few times and backing off in between attempts.