Next.js Discord

Discord Forum

Nextjs notFound() and useEffect bug

Answered
naya posted this in #help-forum
Open in Discord
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:
"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...
View full answer

37 Replies

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
So is there anyway to call a notFound inside of a client component?
@joulev just move it outside useEffect, it should work
nop does the same thing
then i think the cause of the bug is not in this component :thinkies:
your component looks good
@naya So is there anyway to call a notFound inside of a client component?
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`
    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();
then the bug is not there. the component looks good
might be a bug inside of nextjs?
can you make a minimal reproduction repository?
no this is not a nextjs bug
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 fine
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
@joulev interesting, haven't tried this but i see no reason it wouldn't work though <:thinkies:1009340136020004904>
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
well this works for me though :thinkies:
@joulev well this works for me though <:thinkies:1009340136020004904>
try redirecting to a client component
@naya try redirecting to a client component
no difference. things still work fine
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
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
@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
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