redux-toolkit: RTKQ: On success/error callbacks

(this is feature request, not a bug!)

It would be really nice to be able to pass an onSuccess/onError callback to useQuery calls

onSucess would only be called when the query completes and would contain the data (and maybe other parts of UseQueryResult like requestId, endpointName, startedTimeStamp, fulfilledTimeStamp). onError would only be called when the query fails and would contain the error.

These could be passed as part of UseQueryOptions.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 4
  • Comments: 16 (7 by maintainers)

Most upvoted comments

I’ve been wondering about this myself but with mutations. Thankfully we can get the result of a mutation but it feels like I’m colouring outside the lines a little bit. Here’s the pattern I’ve been using:

const [deleteItem, { isLoading }] = useDeleteItemMutation();

const handleDelete = async () => {
  const result = await deleteItem({ id: myItem.id });
  if ('error' in result) {
    addToast('Uh oh something bad happened!')
  } else {
    addToast('Item deleted')
    redirectTo(routes.items.index)
  }
}

This is working fine for me, but I don’t think there’s anything similar for queries (not that I’ve needed it.)

The reason I like to do this in the component is because I might have one mutation or query that multiple components use and they all need to do different things in the success/error scenarios.

This is not in there by design.

I mean, when would it trigger?

Imagine, you have component A without an onSuccess callback that is mounted first. It triggers a request, that leads to a cache entry.

Now component B mounts. It has a onSuccess callback and uses the same query. Now that will never fire, since there is already a cache entry and a request is never made.

But if B mounts before A, it fires.

This would be highly confusing behavior. Even worse, what if both components have that callback? Only one of the two will ever fire.

Therefore, lifecycle events only exist on endpoint level (see onQueryStarted), but not on component level.

For everyone who still wants to push for this (and there are a lot of thumbs in both directions, and other emojis on some of the posts here):

TanStack Query just made the decision official that these callbacks will be removed in their next major version, and the accompanying blog post gives many more arguments than I have already given.

You can read the blog post here - maybe it gives some additional context explaining our stance here.

@tomeronen if you update your RTK to 1.7, they do.

Yup, that approach works fine here! I just know Dominik had a hell of a time on Twitter this weekend explaining that no, mutation callbacks aren’t going away

So since useLazyQuery now supports this and I am very sure that we will not also add anything like this to useQuery, I’m going to close this issue.

If the value is already cached, wouldn’t it be possible to call onSuccess with the cached value when the component mounts? I do see how onError wouldn’t work in that case, since errors probably aren’t cached (?)

My use case is that I have a useLazyQuery that is triggered when a user takes an action. Depending on the result of the query, either an error message is rendered (using the result of the query; this is not an actual error but a successful 200 that contains information) or a redirect is done with window.location.assign() (also using the result of the query).

Is onQueryStarted the suggested way of doing side effects that are the result of an async call? For example, redirecting or setting something in localstorage or cookies. I can see the reasoning that the side-effects should only happen once and components shouldn’t have to care about side effects.