I am using Suspense
from React, and Await
from React-Router-DOM to wait for a promise and return JSX on resolve, but in most cases I want to call some functions like navigate
or something else, then the functions are called twice. I want to prevent that.
Loader
export const Loader = async ({ params }) => {
CheckAuth();
let fetch_data = fetchApi('auth/activate-account', 'POST', { verify_token: params.verify_token });
return defer({ loaderPromise: fetch_data });
}
// this loader is called in the Route loader prop
const VerifyToken = () => {
const loaderData = useLoaderData();
const navigate = useNavigate();
const { showAlert } = useGeneral();
return (
<React.Suspense fallback={<PreLoader />}>
<Await resolve={loaderData.loaderPromise}>
{(resolvedData) => {
if (resolvedData.type === "warning") {
showAlert(resolvedData.type, resolvedData.msg);
navigate('/Auth/Login', { replace: true });
return null;
}
return (
{ JSX }
);
}}
</Await>
</React.Suspense>
);
};
This causes calling the navigate
and showAlert
functions twice. I want to prevent that or use another approach or other methods.
I tried this:
let loaderRef = React.useRef(false);
<React.Suspense fallback={<PreLoader />}>
<Await resolve={loaderData.loaderPromise}>
{(resolvedData) => {
if (!loaderRef.current) {
showAlert(resolvedData.type, resolvedData.msg);
loaderRef.current = true;
setTimeout(() => {
navigate('/Auth/Login', { replace: true });
}, 0);
return null;
}
}}
</Await>
</React.Suspense>
This works but not efficient in most cases.
2
Answers
I don’t have a full picture to help you, but I’ll try to guest
Are you using react in StrictMode in development?
It will make React rerender twice every component trying to avoid errors
If is not the case, please provide a way to test the application
https://react.dev/reference/react/StrictMode#strictmode
I suspect there is some rendering issue being exposed by a
React.StrictMode
component higher up the ReactTree, specific lifecycle functions are double-invoked in non-production builds to expose logical issues in your code like unintentional side-effects.Abstract the unintentional side-effect of showing the alert and navigating into a React component that can use the
useEffect
hook to correctly issue an intentional side-effect to show the alert and conditionally redirect or render the specified JSX content.Example: