I was developing a useUser Hook for per-page authentication. I have implemented the useUser hook normally and Redirecting works fine accordingly. But I am getting the above error.
Abort fetching component for route: "/login"
How can I fix useUserHook to solve it??
//useUser.tsx
const useUser = ({ redirectTo, redirectIfFound }: IParams) => {
const { data, error } = useRequest("authed", isAuthed);
const user = data?.data;
const hasUser = user;
useEffect(() => {
if (!redirectTo) return;
if (
// If redirectTo is set, redirect if the user was not found.
(redirectTo && !redirectIfFound && !hasUser) ||
// If redirectIfFound is also set, redirect if the user was found
(redirectIfFound && hasUser)
) {
Router.push(redirectTo);
}
}, [redirectTo, redirectIfFound, hasUser]);
return error ? null : user;
};
//index.tsx
const Home: NextPage = () => {
const user = useUser({ redirectTo: "/login" });
if (user === undefined || user === false) {
return <div>Loading...</div>;
}
return (
<div>
<Head>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<div>Home</div>
</div>
);
};
UseRequest Hook returns true and false as return values.
Ensure that you only call router.push()
once throughout all potential re-executions of useEffect
with the help of state:
const [calledPush, setCalledPush] = useState(false); // <- add this state
// rest of your code [...]
useEffect(() => {
if (!redirectTo) return;
if (
(redirectTo && !redirectIfFound && !hasUser) ||
(redirectIfFound && hasUser)
) {
// check if we have previously called router.push() before redirecting
if (calledPush) {
return; // no need to call router.push() again
}
Router.push(redirectTo);
setCalledPush(true); // <-- toggle 'true' after first redirect
}
}, [redirectTo, redirectIfFound, hasUser]);
return error ? null : user;
};
useEffect
potentially gets called multiple times if you have more than one dependency (Also happens with React Strict Mode enabled, but in this case there seems to be no error), and (re-)calling router.push()
multiple times within the same Next.js page in different places/throughout different re-renders seems to cause this error in some cases, as the redundant router.push()
call(s) will have to be aborted, because the current page-component unmounts due to the successful, previously called router.push()
.
If we keep track of whether we have already called router.push
via the calledPush
state as in the code snippet above, we omit all redundant router.push()
calls in potential useEffect
re-executions, because for all subsequent useEffect
executions the state value calledPush
will already be updated to true
as useEffect
gets triggered after re-renders, hence after setCalledPush(true)
takes effect.