Reputation: 9672
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
Reputation: 433
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>
)
}
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
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
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.
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
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