Nextjs notFound() and useEffect bug
Answered
naya posted this in #help-forum
nayaOP
Hello I'm having an issue with the notFound from nextjs 14.2.4 where if I call not found inside of a a useEffect it will just make this error.
My code:
My code:
"use client";
export default function VerifyEmailID({ params: { id } }: { params: { id: string } }) {
const [emailSent, setEmailSent] = useState(false);
const { data, isLoading } = useSWR(`verifyemail`, (id) => confirmUserEmail(id));
useEffect(() => {
if (!isLoading && (!data?.success || data?.error === "EMAIL_EXPIRED")) {
notFound();
}
}, [isLoading]);
return (
<div className="flex h-full items-center justify-center">
{data?.success ? (
<div className="space-y-4 text-center">
<h1 className="text-whitey text-5xl font-semibold">Email confirmed</h1>
<Link href="/login" className="block">
<Button variant={"expandIcon"} Icon={ArrowRightIcon} iconPlacement="left">
Login
</Button>
</Link>
</div>
) : data?.success === "EMAIL_EXPIRED" ? (
<div className="space-y-2 text-center">
<h1 className="text-whitey text-5xl font-semibold">Email expired</h1>
<p className="text-whitey text-lg text-muted">The verification email is expired.</p>
<Button disabled={emailSent}>
Resend Email
</Button>
</div>
) : (
<h1 className="text-whitey text-5xl font-semibold">Loading...</h1>
)}
</div>
);
}Answered by naya
omg thanks @joulev while looking at all my use effects calls i realize where the problem was, it was a useEffect i kept doing between re-renders of page to grab the session...
37 Replies
nayaOP
Basically it keeps doing request to this URL and this makes it bug because it does render it but then after the useEffect finish his job it's breaking
nayaOP
So is there anyway to call a notFound inside of a client component?
@joulev just move it outside useEffect, it should work
nayaOP
nop does the same thing
then i think the cause of the bug is not in this component 

your component looks good
@naya So is there anyway to call a notFound inside of a client component?
nayaOP
thats more of the question
other than the
useEffect part – notFound should be called during rendering not during an effect – but for that one simply moving the notFound outside useEffect should work@naya So is there anyway to call a notFound inside of a client component?
yes... by moving
notFound outside the useEffect@joulev yes... by moving `notFound` outside the `useEffect`
nayaOP
const [emailSent, setEmailSent] = useState(false);
const [emailState, setEmailState] = useState<("EXPIRED" | "INVALID" | "VALID") | null>(null);
const { data, isLoading } = useSWR(`verifyemail`, () => confirmUserEmail(id));
useEffect(() => {
if (!isLoading) {
if (data?.success) setEmailState("VALID");
else if (data?.error === "EMAIL_EXPIRED") setEmailState("EXPIRED");
else setEmailState("INVALID");
}
}, [data]);
if (!isLoading && emailState === "INVALID") notFound();@joulev yes... by moving `notFound` outside the `useEffect`
"use client";
function Component() {
const [clicked, setClicked] = useState(false);
if (clicked) notFound();
return <button onClick={() => setClicked(true)}>Click me</button>;
}if the file is empty it works
but now it doesnt
@naya js
const [emailSent, setEmailSent] = useState(false);
const [emailState, setEmailState] = useState<("EXPIRED" | "INVALID" | "VALID") | null>(null);
const { data, isLoading } = useSWR(`verifyemail`, () => confirmUserEmail(id));
useEffect(() => {
if (!isLoading) {
if (data?.success) setEmailState("VALID");
else if (data?.error === "EMAIL_EXPIRED") setEmailState("EXPIRED");
else setEmailState("INVALID");
}
}, [data]);
if (!isLoading && emailState === "INVALID") notFound();
function getEmailState(data) {
if (data?.success) return "VALID";
if (data?.error === "EMAIL_EXPIRED") return "EXPIRED";
return "INVALID";
}
const { data, isLoading } = useSWR(`verifyemail`, () => confirmUserEmail(id));
const emailState = isLoading ? null : getEmailState(data);
if (!isLoading && emailState === "INVALID") notFound();@joulev tsx
function getEmailState(data) {
if (data?.success) return "VALID";
if (data?.error === "EMAIL_EXPIRED") return "EXPIRED";
return "INVALID";
}
const { data, isLoading } = useSWR(`verifyemail`, () => confirmUserEmail(id));
const emailState = isLoading ? null : getEmailState(data);
if (!isLoading && emailState === "INVALID") notFound();
nayaOP
still not working
then the bug is not there. the component looks good
nayaOP
might be a bug inside of nextjs?
can you make a minimal reproduction repository?
no this is not a nextjs bug
nayaOP
I found it
I had a component that was rendering inside of the layout + not-found
@joulev is it normal i can't use <Link> inside of notFound?
@naya <@484037068239142956> is it normal i can't use <Link> inside of notFound?
no it isn't. i can use <Link> in
not-found.js files just finenayaOP
But if the Link redirect to a page where a component like a Header is already render and the page you are trying to redirect has a the same Header component it will break
@naya But if the Link redirect to a page where a component like a Header is already render and the page you are trying to redirect has a the same Header component it will break
interesting, haven't tried this but i see no reason it wouldn't work though 

@joulev interesting, haven't tried this but i see no reason it wouldn't work though <:thinkies:1009340136020004904>
nayaOP
Well let me do one more test but i think it's doing that
import { ArrowLeftIcon } from "lucide-react";
import Link from "next/link";
import { Button } from "@/components/ui/button";
export default function NotFound() {
return (
<main className="flex min-h-[45.5vh] justify-center px-3.5 md:px-7">
<div className="flex w-full max-w-page items-center justify-center">
<div className="space-y-4 text-center">
<h1 className="text-whitey text-6xl font-semibold">Page Not Found</h1>
<p className="mt-4 text-lg text-muted">The page you are looking for does not exist.</p>
<Link href="/register" className="block">
<Button
variant="expandIcon"
className="w-full"
size={"landing"}
Icon={ArrowLeftIcon}
iconPlacement="left"
>
Back Home
</Button>
</Link>
</div>
</div>
</main>
);
}but a simple <a> works
@joulev well this works for me though <:thinkies:1009340136020004904>
nayaOP
try redirecting to a client component
but i think since <a> works, it is a good enough choice for you at the moment. long term you should fix those setState errors in the console, i think they have something to do with this bug
@joulev but i think since <a> works, it is a good enough choice for you at the moment. long term you should fix those setState errors in the console, i think they have something to do with this bug
nayaOP
import Header from "@/components/page/root/layout/Header";
export default function AuthLayout({ children }: { children: React.ReactNode }) {
return (
<>
<Header />
<main className="relative flex min-h-[calc(100vh-70px)] items-center justify-center overflow-hidden">
<div className="max-w-page">{children}</div>
</main>
</>
);
}if i remove the Header the links work
nayaOP
@joulev Basically inside of my page I have a useEffect his layout parent has also a component inside with a useEffect (Header) and when it changes page I feel like they are conflicting because if i remove either one of them it works
nayaOP
omg thanks @joulev while looking at all my use effects calls i realize where the problem was, it was a useEffect i kept doing between re-renders of page to grab the session...
Answer