I’m building an app using NextJS (app router system). I’m building the sign-up workflow, using NextAuth, and Resend. I’m using the newly available Resend provider from NextAuth.
Here is the workflow explained:
- Sign-up form to get the user’s email.
- When submitted, I’m calling a server action which triggers the signIn() method from NextAuth.
- This sends a custom email, with a validation code that I created. A verificationToken is automatically created in DB, using the NextAuth Adapter for Prisma.
- The user clicks on the validation button inside the email to be redirected to my validation page where he can input the validation code he received (an 6 digits OTP).
- When the form is submitted, it triggers a server action that checks if the code is correct and perform a redirect to the onboarding page.
My process works until the 5th step, where I’m being redirected to the onboarding page. I can see a session token created in my cookies, and I can also see that this line const session = await auth();
is storing my session object inside my root layout.tsx
. Same for the console.log("Session in Navbar: ", session);
inside my Navbar.tsx
component.
However it seems that isLoggedIn is not evaluate to true inside my tsx component (Navbar), and I can see that the logs from terminal and the ones from the browser console are not the same (isLoggedin=true on server, and false on browser).
When I manually reload the onboarding page, using cmd+R, my Navbar is updating as I want.
my root layout.tsx
import "./globals.css";
import { auth } from "../../auth";
import { cn } from "@/lib/utils";
import { Poppins } from "next/font/google";
import { Navbar } from "@/components/Navbar";
import { SessionProvider } from "next-auth/react";
import { Toaster } from "@/components/ui/toaster";
const fontHeading = Poppins({
subsets: ["latin"],
display: "swap",
variable: "--font-heading",
weight: ["100", "200", "300", "400", "500", "600", "700", "800", "900"],
});
const fontBody = Poppins({
subsets: ["latin"],
display: "swap",
variable: "--font-body",
weight: ["100", "200", "300", "400", "500", "600", "700", "800", "900"],
});
export default async function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const session = await auth();
console.log("Session in Layout: ", session);
return (
<html lang="en">
<body
className={cn(
"antialiased",
fontHeading.variable,
fontBody.variable
)}
>
<SessionProvider session={session}>
<Navbar />
<section className="px-[5%]">{children}</section>
</SessionProvider>
<Toaster />
</body>
</html>
);
}
my Navbar component
"use client";
import Link from "next/link";
import { Sheet, SheetTrigger, SheetContent } from "@/components/ui/sheet";
import { NavLink, Button } from "@/components/ui/button";
import Logo from "./Logo";
import { Menu } from "lucide-react";
import { Separator } from "./ui/separator";
import { useEffect, useState } from "react";
import { signOut, useSession } from "next-auth/react";
export function Navbar() {
const { data: session, status, update } = useSession();
const [isSheetOpen, setSheetOpen] = useState(false);
const [isLoggedIn, setIsLoggedIn] = useState(false);
const handleCloseSheet = () => {
setSheetOpen(false);
};
useEffect(() => {
if (status === "authenticated") {
setIsLoggedIn(true);
update();
} else {
setIsLoggedIn(false);
}
}, [status, session]);
console.log("Session in Navbar: ", session);
console.log("Current time is: ", new Date().toLocaleTimeString());
return (
// I'm performing an if condition on the value of isLoggedIn to modify the UI of the Navbar here
- I tried refresh the page using
useRouter()
hook inside my Navbar component. - I tried a
window.location.reload()
to simulate a CMD+R. - I tried using
useEffect()
inside the Navbar component.