How to wait for something with React-Query?

Viewed 6471

I'm new to react query and loving it so far. I get that it is mainly a UI library. So it's great for handling/displaying errors, loading states. But often I find myself wanting to wait for some specific action in an async way. So, I'd love to be able to wait for a promise to return before triggering an action e. g. a redirect.

Here is an example:

const NewPostForm = props => {
  const history = useHistory();
  const mutatePostInfo = useUpdatePost(); // useMutate hook
  const [value, setValue] = useState("")
  
  const handleSubmit = () => {
    mutatePostInfo.mutate(value);
    // I WANT TO: wait for the action to complete before redirecting
    history.push("/new-route/")
  }
  
  return (
    <form onSubmit={handleSubmit}>
      <input value={value} onChange={(e) => setValue(e.target.value)} />
    </form>
  )
}
3 Answers

The mutate function returned by useMutation takes options as a second argument, and you can use the onSuccess option to execute something when the mutation succeeds:

mutatePostInfo.mutate(
    value,
    {
        onSuccess: () => history.push("/new-route/")
    }
);

There is also the onError (for errors) and the onSettled callback (if you want to redirect in case of success or error).

for waiting for other values or functions to be completed that do not have an onSuccess function, you can use dependent queries to halt the query until that value exists / fits your criteria.

https://egghead.io/lessons/react-use-dependent-queries-to-delay-react-query-s-usequery-from-firing-on-render

const [payload, setPayload] = useState();
const someFunc = () => setPayload("data");

const { data } = useQuery(payload && ["queryKey", { payload }],
    queryName
  );

someFunc();

will wait until payload has a value, in this case "data", before it sends it's queryName request, you could also pass in a function with a return value which would wait for that returned value.

You can use Dependent Queries. For instance:

// Get the user
const { data: user } = useQuery(['user', email], getUserByEmail)
     
const userId = user?.id
     
const { isIdle, data: projects } = useQuery(
    ['projects', userId],
    getProjectsByUser,
    {
        // The query will not execute until the userId exists
        enabled: !!userId,
    }
  )
     
// isIdle will be `true` until `enabled` is true and the query begins to fetch.
// It will then go to the `isLoading` stage and hopefully the `isSuccess` stage :)
Related