deecaf
deecaf3d ago

Error: Invalid hook call. (useQuery inside useEffect)

Hi, I'm using clerk + convex in Expo. I'm trying to load user data once the user is set on sign-in from clerk's useUser hook. To do this, I have placed the useQuery hook inside useEffect, which is causing this error. I have also tried putting the useQuery call inside useCallback - that did not throw an error but did not work as intended. Could anyone please suggest me a proper way to achieve this? Thanks. code:
export default function SignIn() {
const { user } = useUser();

function getData(id: string) {
const userData = useQuery(api.users.getUserByClerkId, {
clerkId: id,
});
}
useEffect(() => {
if (user) {
getData(user.id);
}
}, [user]);

return (...)
}
export default function SignIn() {
const { user } = useUser();

function getData(id: string) {
const userData = useQuery(api.users.getUserByClerkId, {
clerkId: id,
});
}
useEffect(() => {
if (user) {
getData(user.id);
}
}, [user]);

return (...)
}
error:
ERROR Warning: Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.

This error is located at:

10 |
11 | export const SignIn = () => {
> 12 | const { user } = useUser();
| ^
13 |
14 | const [clerkId, setClerkId] = useState<string>("");
15 | function getData(id: string) {

Call Stack
SignIn (app/(auth)/sign-in.tsx:12:27)
ScreenContentWrapper (<anonymous>)
RNSScreenStack (<anonymous>)
Layout(./(auth)/_layout.tsx) (<anonymous>)
InitialLayout (<anonymous>)
RootLayout(./_layout.tsx) (<anonymous>)
RNCSafeAreaProvider (<anonymous>)
App (<anonymous>)
ErrorOverlay (<anonymous>)
ERROR Warning: Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.

This error is located at:

10 |
11 | export const SignIn = () => {
> 12 | const { user } = useUser();
| ^
13 |
14 | const [clerkId, setClerkId] = useState<string>("");
15 | function getData(id: string) {

Call Stack
SignIn (app/(auth)/sign-in.tsx:12:27)
ScreenContentWrapper (<anonymous>)
RNSScreenStack (<anonymous>)
Layout(./(auth)/_layout.tsx) (<anonymous>)
InitialLayout (<anonymous>)
RootLayout(./_layout.tsx) (<anonymous>)
RNCSafeAreaProvider (<anonymous>)
App (<anonymous>)
ErrorOverlay (<anonymous>)
No description
No description
2 Replies
erquhart
erquhart3d ago
You can't nest hooks, they have to be called directly from the top scope of a component (or another hook). For this, though, you can avoid the hassle and use the skip arg: https://docs.convex.dev/client/react#skipping-queries
Convex React | Convex Developer Hub
Convex React is the client library enabling your React application to interact
erquhart
erquhart3d ago
export default function SignIn() {
const { user } = useUser();

const userData = useQuery(api.users.getUserByClerkId, user ? {
clerkId: user.id,
} : 'skip');
}

return (...)
}
export default function SignIn() {
const { user } = useUser();

const userData = useQuery(api.users.getUserByClerkId, user ? {
clerkId: user.id,
} : 'skip');
}

return (...)
}
Passing the string "skip" as the sole query arg keeps the query from executing.

Did you find this page helpful?