Xen_mar
Xen_mar

Reputation: 9672

How to wait for something with React-Query?

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>
  )
}

Upvotes: 16

Views: 30066

Answers (4)

Mohammad Reza
Mohammad Reza

Reputation: 433

  1. mutateAsync

useMutation comes with a built-in function called mutateAsync which you can call it with await. read here for more.

const NewPostForm = props => {
  const history = useHistory();
  const mutatePostInfo = useUpdatePost(); // useMutate hook
  const [value, setValue] = useState("")
  
  const handleSubmit = async () => {
    await mutatePostInfo.mutateAsync(value); // waits 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>
  )
} 
  1. mutate and onSuccess

useMutation comes with another function called mutate. The second argument of mutate is an option that overrides options passed to useMutation. the function will fire when the mutation is successful and will be passed the mutation's result. check here for more.

const NewPostForm = props => {
  const history = useHistory();
  const mutatePostInfo = useUpdatePost(); // useMutate hook
  const [value, setValue] = useState("")
  
  const handleSubmit = () => {
    mutatePostInfo.mutate( value, { onSuccess: () => history.push("/new-route/") });
  }
  
  return (
    <form onSubmit={handleSubmit}>
      <input value={value} onChange={(e) => setValue(e.target.value)} />
    </form>
  )
} 

Upvotes: 4

Ruslan Korkin
Ruslan Korkin

Reputation: 5081

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 :)

Upvotes: 5

MintWelsh
MintWelsh

Reputation: 1259

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.

Upvotes: 3

TkDodo
TkDodo

Reputation: 28753

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).

Upvotes: 9

Related Questions