Next.js Discord

Discord Forum

change button in navbar on login

Answered
Large garden bumble bee posted this in #help-forum
Open in Discord
Large garden bumble beeOP
Hello everyone. I am rather new to nextjs and I ran into a problem I am trying to fix for quite a while now so I would appreciate your help.

I have 2 components, my Navbar and my NavbarButton. the outcome i want is the following: if there is a session show the logout button, if there is no session dont show anything.
right now if i login into my application i have 2 solutions i am not happy with.
- serverside-component: if i make the navbar a serverside component button does not show after a successful login until i refresh the page
- clientside-component: if i make the navbar a client side component the button does show immediately and i dont need to refresh the page but every time i refresh the button disappears for a short time

I will put the code for the server- and clientside navbar and my navbar button in the next messages. I am not sure, if this is all the code you need but if not i will gladly provide you with more. i dont need a full solution, i will also gladly take hints and links, which will guide me to the right direction. thanks in advance!
Answered by Ray
yes because of router cache, so your NavbarButton not rerender after you signin, you have to use router.refresh to invalidate the router cache
https://nextjs.org/docs/app/building-your-application/caching#invalidation-1
View full answer

19 Replies

Large garden bumble beeOP
NavbarButton.tsx (serverside)
//'use client'
import Link from "next/link"
import Image from "next/image"
import styles from './Navbar.module.css'
import NavbarButton from "./NavbarButton"
import { getServerSession } from "next-auth"
import { signOut, /*useSession*/ } from "next-auth/react"



export default async function Navbar() {

    const session = await getServerSession()
    // const { data: session } = useSession()


    return (
        <div className={styles.container}>
            <Link href="/">
                <Image
                priority={true}
                width={125}
                height={40}
                className="logo"
                src="/logo_torquoise.png"
                alt="logo"
                ></Image>
            </Link>
            <NavbarButton session={session}/>
        </div>
    )
}
NavbarButton.tsx (clientside)
'use client'
import Link from "next/link"
import Image from "next/image"
import styles from './Navbar.module.css'
import NavbarButton from "./NavbarButton"
// import { getServerSession } from "next-auth"
import { signOut, useSession } from "next-auth/react"



export default function Navbar() {

    // const session = await getServerSession()
    const { data: session } = useSession()


    return (
        <div className={styles.container}>
            <Link href="/">
                <Image
                priority={true}
                width={125}
                height={40}
                className="logo"
                src="/logo_torquoise.png"
                alt="logo"
                ></Image>
            </Link>
            <NavbarButton session={session}/>
        </div>
    )
}
NavbarButton.tsx:
'use client'
import { signOut } from "next-auth/react"
import styles from './Navbar.module.css'
import Link from "next/link"

export default function NavbarButton({session}: any) {
  return (
    <>
    {session ? (
        <Link href={ "/" }>
            <button className={styles.logoutButton} onClick={() => signOut()}>Logout</button>
        </Link>
    ) : null}
    </>
  )
}
Large garden bumble beeOP
you mean client component right? when using it on server component like this
import { redirect, useRouter } from 'next/navigation';
const router = await useRouter()
router.refresh()

i get the error useRouter only works in Client Components

and when i use it like this:
import { useRouter } from 'next/router';
const router = await useRouter()
router.refresh()

i get the error Property 'refresh' does not exist on type 'NextRouter'.
yes after you run the signin function
and does the NavbarButton.tsx (serverside) button show if you run router.refresh() after the login function?
Large garden bumble beeOP
it seems like i broke my code some time ago. i will answer when i get it to work again
Large garden bumble beeOP
thanks a lot i the router.refresh after the signIn function worked.

LoginForm.tsx
const res = await signIn("credentials", {
          redirect: false,
          username: formValues.username,
          password: formValues.password,
          callbackUrl,
        });
  

        setLoading(false);
  
        if (!res?.error) {
            router.refresh()  //changed redirect to this
        } else {
          setError("invalid username or password");
        }


page.tsx (for login)
export default async function LoginPage() {
    const session = await getServerSession(options)
    if (session) {
        redirect("/")
    }

    return (
        <div className={styles.page}>
            <LoginForm />
        </div>
    )
}


not sure if this is the prettiest way but it works. i changed the redirect('/') after the signin function to router.refresh() and on my login site i check if the user is already logged in and if so i redirect the user to /
yes because of router cache, so your NavbarButton not rerender after you signin, you have to use router.refresh to invalidate the router cache
https://nextjs.org/docs/app/building-your-application/caching#invalidation-1
Answer
Asian black bear
Yes I was thinking about it but I read somewhere router.refresh leads unexpected behavior.
Asian black bear
I don't know where I read it. I have to check history page.
BTW, what do you recommend to use when user sign out, push or replace ? I'm confuse about it.
I think both are fine but I would use replace
Asian black bear
Thanks.