Skip to content

fix(query-core): do not fetch if queryFn is skipToken #9301

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

tmkx
Copy link
Contributor

@tmkx tmkx commented Jun 22, 2025

sometimes I want to call prefetch with a condition:

Repro:

usePrefetchQuery({
  queryKey: ['todo', id],
  queryFn: id ? () => getTodo({ id }) : skipToken,
});

but there will be an error:

Attempted to invoke queryFn when set to skipToken. This is likely a configuration error. Query hash: '["todo",null]'

@TkDodo
Copy link
Collaborator

TkDodo commented Jun 27, 2025

our usual stance is that imperative functions don’t need those guards because you can wrap them in an if(id) block. enabled / skipToken are a way to have “conditional hooks”, but this isn’t necessary for imperative functions.

@TkDodo
Copy link
Collaborator

TkDodo commented Jun 27, 2025

also, we would need this on queryClient.fetchQuery as well, but we can’t because that returns Promise<TData>.

@TkDodo TkDodo closed this Jun 27, 2025
@tmkx
Copy link
Contributor Author

tmkx commented Jun 27, 2025

thanks for your reply. I agree with you, but what's the idiomatic way to conditionally prefetch a query in react hooks since it cannot use if(id)? I pass the skipToken to usePrefetchQuery, but it raises a console error.

@TkDodo
Copy link
Collaborator

TkDodo commented Jun 27, 2025

we had the same question come up regarding enabled. If we do something, we should have a check in usePrefetchQuery. But I would find it weird to see a call to usePrefetchQuery that doesn’t prefetch. Maybe that hook was a mistake in the first place. What are you using it for?

@tmkx
Copy link
Contributor Author

tmkx commented Jun 27, 2025

I use it to initiate anticipated requests in advance to reduce the time consumed by waterfall requests. I believe I can implement it using a different approach, such as useEffect combined with if(id). I'm just curious why we're allowed to pass skipToken to usePrefetchQuery but receive an error at the end.

@TkDodo
Copy link
Collaborator

TkDodo commented Jun 27, 2025

I'm just curious why we're allowed to pass skipToken to usePrefetchQuery but receive an error at the end.

yeah we should fix that on type level. like we’ve done it in useSuspenseQuery. Would you like to give this a shot?

@TkDodo
Copy link
Collaborator

TkDodo commented Jun 27, 2025

the docs also say:

it should be used just to fire a prefetch during render, before a suspense boundary that wraps a component that uses useSuspenseQuery.

with suspense, you also have no skipToken / enabled. If you don’t use suspense, why wouldn’t the component that you prefetch just render ? where’s the waterfall coming from?

@tmkx
Copy link
Contributor Author

tmkx commented Jun 27, 2025

thank you for your clarification. in my scenario, I receive an optional id from the url. there is a nested component tree that will cause waterfall queries. therefore, I want to prefetch some data that will be necessary.

the detail list and feedback list are two APIs fetched by collection id and connected by the detail id. feedback is loaded after the message is rendered, without prefetching.

<Collection id={optionalCollectionId}>
  {prefetchFeedbacks}
  <Suspense>
    <List>
      <Detail>
        <Feedback /> {/* select: feedbacks => feedbacks.find(fb => fb.detailId === detail.id) */}
      </Detail>
      <Detail>
        <Feedback />
      </Detail>
      ...
    </List>
  </Suspense>
</Collection>

function Detail({ collectionId, detail }) {
  const { data: feedback } = useQuery({
    queryKey: ['feedbacks', collectionId],
    queryFn: () => fetchFeedbacks(collectionId),
    select: feedbacks => feedbacks.find(fb => fb.detailId === detail.id),
  });

  return <>{/* ... */}</>;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants