I use RTK Query for data fetching and I am having a small issue in one of the use cases.
I use a mutation to verify the email address of the app user, as follows:
// ...imports
const ConfirmEmail = () => {
const [params] = useSearchParams();
const [confirmEmail, { isLoading, isSuccess, isUninitialized, error }] =
useConfirmEmailMutation();
useEffect(() => {
if (isUninitialized) {
confirmEmail({
email: params.get('email'), // from the verification link
code: params.get('code'), // from the verification link
})
.unwrap()
.then(() => {
// handling success...
})
.catch((e) => {
// handling error...
});
}
});
// ...other component code
}
The problem is that with StrictMode
the mutation is running twice in development and it is causing a concurrency error at the API side. I see two network requests in the dev tools one is successful and the other is not and depending on which one runs first the component is showing inconsistent result.
I am aware that this will only happen during development and I tried to follow the instructions in the official react documentation and I tried to use fixedCacheKey
as described here but I wasn't able to make this work with RTK Query so that I get a consistent result during development.
Is there a way, or am I missing something?
Edit: my question falls into the same category as this question but it is more specific to RTK Query. Because in RTK Query if a component tries to make the same query as an existing one, no request will be performed (as mentioned here). However, what I am trying to do is a mutation in order to confirm the email address of a user (following a click on a link sent by email). Mutations do not follow the same rule as mentioned here.
useEffect
cleanup function wasn't helpful and this is not like buying a product example.
Based on the discussions below, the available options were:
- Using a query instead of a mutation. But this won't be semantically correct.
- Force the user to click -again- on a button to initiate the "confirm email" mutation. Which is repetitive and not user-friendly.
- Use a
ref
to track whether a mutation is already running. Which is what I implemented at the end as follows:
// ...imports
const ConfirmEmail = () => {
const verifiying = useRef(false);
const [params] = useSearchParams();
const [confirmEmail, { isLoading, isSuccess, isUninitialized, error }] =
useConfirmEmailMutation();
useEffect(() => {
const isVerifying = verifiying.current;
if (isUninitialized) {
verifiying.current = true;
confirmEmail({
email: params.get('email'), // from the verification link
code: params.get('code'), // from the verification link
})
.unwrap()
.then(() => {
// handling success...
})
.catch((e) => {
// handling error...
});
}
});
// ...other component code
}