T
TanStack4y ago
mute-gold

set timeout to navigate on onSuccess when mutating

I am having problems with the below and wondered if anyone can help? Before migrating to RQ I used a setTimeout with Redux to solve the below: A user chooses a country to onboard in. The country is posted to the backend, we wait 4 seconds, the user object is fetched which includes the onboarding country and the user is redirected. (without the onboarding country being present in the user object we refuses the re-direct due to permissions) The problem I have with RQ is that even after onSuccess / onSettled, the user object is still not fetched in time before navigation, so the redirection fails. OLD: Redux
const onClickHandler = async () => {
await postInternationalCountryCode();
await dispatch(fetchUser());
setIsVerifiedInternational(true);
}
};

useEffect(() => {
if (isVerifiedInternational) {
setIsLoading(true);
const navigationTimer = setTimeout(() => {
history.push("/toTheDashboard");
}, 6000);
}
}, [isVerifiedInternational]);
const onClickHandler = async () => {
await postInternationalCountryCode();
await dispatch(fetchUser());
setIsVerifiedInternational(true);
}
};

useEffect(() => {
if (isVerifiedInternational) {
setIsLoading(true);
const navigationTimer = setTimeout(() => {
history.push("/toTheDashboard");
}, 6000);
}
}, [isVerifiedInternational]);
with RQ
const onClickHandler = async () => {
putInternationalCountryCode(countryCode);
}
};

const { mutate: putInternationalCountryCode, isLoading, isError } = postInternationalCountryCode();


export const postInternationalCountryCode = () => {
const queryClient = useQueryClient();
const history = useHistory();

return useMutation(
async (countryCode) =>
await axios({
url: foo,
method: "put",
data: bar,
responseType: "json"
}),
{
onSuccess: () => {
queryClient.invalidateQueries(["user"]);
},
onSettled: () => {
history.push("/toTheDashboard");
}
}
);
};
const onClickHandler = async () => {
putInternationalCountryCode(countryCode);
}
};

const { mutate: putInternationalCountryCode, isLoading, isError } = postInternationalCountryCode();


export const postInternationalCountryCode = () => {
const queryClient = useQueryClient();
const history = useHistory();

return useMutation(
async (countryCode) =>
await axios({
url: foo,
method: "put",
data: bar,
responseType: "json"
}),
{
onSuccess: () => {
queryClient.invalidateQueries(["user"]);
},
onSettled: () => {
history.push("/toTheDashboard");
}
}
);
};
6 Replies
continuing-cyan
continuing-cyan4y ago
Question: is this the server or the client which refuses to redirect? If it is the client, then I assume that you need to have the updated user somewhere in RQ cache and then the following code could help.
onSuccess: () => {
// Force user refetch the user thanks to staletime 0
await queryClient.fetchquery(["user"], {staletime:0})
// Once refetched, navigate
history.push("/toTheDashboard");
onSuccess: () => {
// Force user refetch the user thanks to staletime 0
await queryClient.fetchquery(["user"], {staletime:0})
// Once refetched, navigate
history.push("/toTheDashboard");
If this is the server, then not sure you need anything: the mutation should update the user server-side and return ok when done. So the redirection could be done in the onSuccess.
mute-gold
mute-goldOP4y ago
The refusal to direct logic is client side so it can be looked at, but would have been nice to keep that existing logic and manage everything in the useMutation. But the code above does fetch the user super quick so I think I am close. The async is missing from your code 🙂
onSuccess: async () => {
// Force user refetch the user thanks to staletime 0
await queryClient.fetchquery(["user"], {staletime:0})
// Once refetched, navigate
history.push("/toTheDashboard");
onSuccess: async () => {
// Force user refetch the user thanks to staletime 0
await queryClient.fetchquery(["user"], {staletime:0})
// Once refetched, navigate
history.push("/toTheDashboard");
continuing-cyan
continuing-cyan4y ago
Yep missing async You should no more have to bother about timing
mute-gold
mute-goldOP4y ago
but the code you shared works when I remove the refusal to direct logic so may re-look at how we manage that instead. RQ is doing a good job of mutating and navigating so don't really want to add anything extra to that particular function.
continuing-cyan
continuing-cyan4y ago
Indeed, you might have to adapt your logic to fit RQ behaviours. If the control is done on the client-side, you could rely on the user you have in the cache. This way, on the onSuccess of the mutation, you would just have to invalidate the 'user' query. Then in the page you are redirected to, just call a useUser hook relying on RQ to check if it has the expected country property. This has the advantage of being "always true", regardless of the fact that you are coming from a mutation or not.
mute-gold
mute-goldOP4y ago
Yep makes sense. Thanks 🙏

Did you find this page helpful?