Reputation: 1
Hello good people and fellow developers.
I have a problem that I am facing at the moment. I have a Navbar component that is called in my root Layout folder right above the {children} so that it is available across the entire application.
When no user is signed in then the sign up and sign in buttons are obviously available but my problem is that when a user signs up or in then the Navbar does not update because it is not a path so I can't use revalidateParth in the register action or login action.
How can I put an active "listener" on my navbar to update when a user is actually logged in.
Here is the code to reverence:
"use client";
import { CurrentUser } from "@/lib/services/models/CurrentUser.model";
import { getCurrentUser } from "@/lib/services/user.service";
import Link from "next/link";
import { useEffect, useState } from "react";
import RegisterUser from "../Registration/Registration";
import ToggleTheme from "../Theme/ToggleTheme";
import AvatarDropdownMenu from "./AvatarDropdownMenu";
import LoginUserComponent from "../Login/Login";
import Image from "next/image";
import logo from "../../../public/ForexRevolution.svg";
import { cn } from "@/lib/utils";
import { buttonVariants } from "../ui/button";
import { revalidateTag } from "next/cache";
const Navbar = () => {
const [user, setUser] = useState<CurrentUser | null>(null);
const [scrolled, setScrolled] = useState(false);
useEffect(() => {
const getUsers = async () => {
try {
const users = await getCurrentUser();
if (users) {
setUser(users);
}
} catch (error) {
console.error("Error fetching user details:", error);
}
};
getUsers();
}, []);
useEffect(() => {
const handleScroll = () => {
const isScrolled = window.scrollY > 0;
setScrolled(isScrolled);
};
// Add event listener
window.addEventListener("scroll", handleScroll);
// Clean up
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return (
<nav
className={`flex z-50 sticky top-0 justify-between items-center lg:px-20 md:px-10 px-5 py-2.5 lg:h-20 md:h-16 h-12 border-b transition-colors duration-700 ${
scrolled
? "bg-white border-blue-600"
: "border-gray-200 dark:border-blue-200 dark:bg-white dark:text-black bg-white"
}`}
>
<div>
{user ? (
<>
<Link href={"/dashboard"}>
<Image src={logo} alt="Logo" width={80} />
</Link>
</>
) : (
<>
<Link href={"/"}>
<Image src={logo} alt="Logo" width={80} />
</Link>
</>
)}
</div>
<div className="flex justify-center items-center gap-5">
{user ? (
<div className="flex items-center justify-center gap-5">
<p className="text-sm font-bold hidden md:block lg:block">
{user.UserName}
</p>
<div className="md:hidden lg:hidden block">
<AvatarDropdownMenu userName={user.UserName} />
</div>
<div className="hidden md:block lg:block">
<AvatarDropdownMenu />
</div>
</div>
) : (
<div className="flex items-center justify-center gape-10">
<RegisterUser />
<span className="h-6 w-px bg-gray-200" aria-hidden="true" />
<LoginUserComponent />
<span className="h-6 w-px bg-gray-200 md:block lg:block hidden" />
<Link
className={`${cn(
buttonVariants({ variant: "default" })
)} md:block lg:block hidden`}
href={"/course"}
>
Free Resources
</Link>
</div>
)}
{/* <div className="mb:block lg:block hidden">
<ToggleTheme />
</div> */}
</div>
</nav>
);
};
export default Navbar;
and the server actions:
// Action to register a new user
export async function registerUserAction(
prevState: UserActionState | null,
data: FormData
): Promise<UserActionState> {
try {
const { firstName, lastName, userName, email, password } =
registerUserSchema.parse(data);
// 1. Does the email already exist?
if (await db.emailExists(email)) {
return {
status: "error",
errors: [
{
path: "email",
message: "Email address is already registered",
},
],
};
}
// 2. UserName unique
if (await db.usernameExists(userName)) {
return {
status: "error",
errors: [
{
path: "userName",
message: "Username is already registered",
},
],
};
}
const hashedPassword = await hashPassword(password);
const expireDate = getTokenExpiryDate();
const token = generateToken();
const verificationToken = generateToken();
if (
!(await db.createUser(
email,
firstName,
lastName,
hashedPassword,
userName,
token,
expireDate,
verificationToken,
"noob"
))
) {
return { message: "Failed to register user", status: "error" };
}
// Only set cookie if prismaClient call was successful
setTokenCookie(token, expireDate);
await sendVerificationEmail(email, userName, verificationToken);
return { message: "Successfully registered user", status: "success" };
} catch (e) {
// In case of a ZodError (caused by our validation) we're adding issues to our response
if (e instanceof ZodError) {
return {
status: "error",
message: "Invalid form data",
errors: e.issues.map((issue) => ({
path: issue.path.join("."),
message: `${issue.message}`,
})),
};
}
return {
status: "error",
message: "Something went wrong. Please try again.",
};
}
}
// Action to log the user in
export async function logInAction(
prevState: UserActionState | null,
data: FormData
): Promise<UserActionState> {
try {
const { email, password } = loginSchema.parse(data);
const user = await db.getUserByEmail(email);
if (user === null) {
return {
status: "error",
message: "Invalid form data",
errors: [
{
path: "email",
message: "Invalid email address or password",
},
],
};
}
if (!(await verifyPassword(password, user.Password))) {
return {
status: "error",
errors: [
{
path: "email",
message: "Invalid email address or password",
},
],
};
}
const expireDate = getTokenExpiryDate();
const token = generateToken();
if (!(await db.setAuthTokenByUserId(user.Id, token, expireDate))) {
return {
status: "error",
message: "Unable to log in, please try again later",
};
}
// Set token only after DB calls done
setTokenCookie(token, expireDate);
return { message: "Successfully registered user", status: "success" };
} catch (e) {
// In case of a ZodError (caused by our validation) we're adding issues to our response
if (e instanceof ZodError) {
return {
status: "error",
message: "Invalid form data",
errors: e.issues.map((issue) => ({
path: issue.path.join("."),
message: `${issue.message}`,
})),
};
}
return {
status: "error",
message: "Something went wrong. Please try again.",
};
}
}
I am trying to update the navbar without having to hard reload the page.
Upvotes: 0
Views: 23