T
TanStack•2y ago
rare-sapphire

Only query when value is not null?

I have a function that returns a useQuery object:
const getSubmissions = (currentProject) => {
const endpoint = endpoints.api.submissions.index.replace(':id', currentProject);

return useQuery({
queryKey: ['submissions'],
queryFn: () => fetch(endpoint).then((res) => res.json()),
staleTime: 10 * 1000
});
};
const getSubmissions = (currentProject) => {
const endpoint = endpoints.api.submissions.index.replace(':id', currentProject);

return useQuery({
queryKey: ['submissions'],
queryFn: () => fetch(endpoint).then((res) => res.json()),
staleTime: 10 * 1000
});
};
which is being used in the following functional component (Next.js):
function SubmissionsTable() {
const { currentProject } = useContext(ProjectContext);

// Problem: this triggers the request even when currentProject is null
const { isLoading, isSuccess, error, data, refetch } = getSubmissions(currentProject);

useEffect(() => {
if (isLoading) return;

if (!isSuccess) {
toast({
variant: 'destructive',
title: "Couldn't fetch submissions",
description: 'Try again later or contact support'
});
return;
}

setSubmissions(validate.data);
}, [isSuccess, data]);

if (isLoading) return <LoadingCard />;

return <DataTable columns={columns} data={submissions} />;
}
function SubmissionsTable() {
const { currentProject } = useContext(ProjectContext);

// Problem: this triggers the request even when currentProject is null
const { isLoading, isSuccess, error, data, refetch } = getSubmissions(currentProject);

useEffect(() => {
if (isLoading) return;

if (!isSuccess) {
toast({
variant: 'destructive',
title: "Couldn't fetch submissions",
description: 'Try again later or contact support'
});
return;
}

setSubmissions(validate.data);
}, [isSuccess, data]);

if (isLoading) return <LoadingCard />;

return <DataTable columns={columns} data={submissions} />;
}
However, getSubmissions(currentProject) triggers the request even when currentProject is null. How do I solve this? I can't just wrap an if-statement around it as the useEffect is dependend on isSuccess & data. I tried adding if (!currentProject) return <LoadingCard />; above it but this causes rendering issues.
3 Replies
national-gold
national-gold•2y ago
there are lots of things not ideal with that code: 1) you shouldn't need to sync data from react-query with react-context 2) getSubmissions needs to be a hook, so it has to start with use 3) all things used inside the queryFn must go into the queryKey 4) to stop a query from firing if a dependency isn't ready, use the enabled option I think you have a bit of reading to do, especially the docs where all these concepts are explained, and then I have a series of blogposts that cover most patterns: https://tkdodo.eu/blog/practical-react-query
Practical React Query
Let me share with you the experiences I have made lately with React Query. Fetching data in React has never been this delightful...
national-gold
national-gold•2y ago
oh and 5) you're missing error handling from fetch for erroneous status codes
rare-sapphire
rare-sapphireOP•2y ago
Thank you, I'll will read into it and will probably get back to you. Some questions I have: 1. I'm syncing data to a context because I'm adding it as a prop to a data table component, is there a better way? Maybe just re-fetch from the cache and using that as a prop instead of the context? 2. When you say hook, you mean just rename it to use****, or are there other benefits? 3. Not sure what you mean. I'm still working on understanding query keys. 4. Thank you, enabled seems to solve it! 5. I know, wanted to keep the sample code as simple as possible @TkDodo 🔮 appreciate your help.

Did you find this page helpful?