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.
CodePudding user response:
useEffect
gets called multiple times as you probably know, especially with more than just one dependency, and calling router.push
multiple times within the same next.js page causes an error I think.
Try ensuring that you only call router.push
exactly once 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)
) {
let calledPushLatest;
setCalledPush(latest => {
calledPushLatest = latest;
return latest;
}
// ^ ensure we get the latest state, because react-state is actually "async" under the hood and takes a bit to reflect updates which may make you call router.push multiple times again
if(calledPushLatest) return; // router.push has already been called
// proceed to redirect
setCalledPush(true);
Router.push(redirectTo);
}
}, [redirectTo, redirectIfFound, hasUser]);
return error ? null : user;
};