0

I am learning Nextjs for the first time, and have experimented by creating a small web app that allows someone to simply register then login. Everything works, except one small issue.

On the page, you can see your status. If you are logged in, it shows your username. If not, it provides a link to the sign in page.

enter image description here

This "Sign In" button is a part of the UserInfoBar component, which is a SSR-component.

The problem is, that when you successfully login, and are redirected to the homepage with router.push('/'), the "Sign In" link is not replaced with your username.

It is only when you refresh the page that your username will show.

enter image description here

I am really at a loss here. The only solution that I can think of is to make UserInfoBar a client component, but then I would have to manually retrieve the session with a fetch call.

Is there not a way to address this from the server side?

src/app/components/UserInfoBar.tsx

import React from 'react'
import Link from 'next/link'
import { getSession } from '../../lib/session'

export default async function UserInfoBar() {
    let sessionData = getSession();

    console.log('on the server')
    console.log(sessionData)

    return (
        <div className="flex-grow text-right px-2 py-1 text-white">
            {sessionData ?
                sessionData.username :
                <Link href="/signin" className='px-2 py-1 text-white '>Sign In</Link>}
        </div>
    )
}

src/app/Header.tsx

import React from 'react'
import Link from 'next/link'
import { Suspense } from 'react';
import UserInfoBar from './components/UserInfoBar'

export default function Header() {
  return (
    <header className='flex justify-center bg-slate-700 mb-7'>
      <div className='flex max-width space-x-4 p-4'>
        <Link href="/" className='px-2 py-1 text-white '>Home</Link>
        <Link href="/decks" className='px-2 py-1 text-white '>Decks</Link>
        <Link href="/signup" className='px-2 py-1 text-white '>About</Link>
        <Suspense fallback={<p>loading...</p>}>
          <UserInfoBar />
        </Suspense>
      </div>
    </header>
  )
}

src/app/page.tsx

import React from 'react'

export default function Page() {
  return (
    <div>
      <h2 className="text-4xl font-extrabold text-slate-700">Demo</h2>
      <div>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam faucibus erat a gravida ultricies.
    </div>
  )
}

src/app/lib/session.ts

import { cookies } from 'next/headers';
import jwt from 'jsonwebtoken'

export const getSession = () => {
    const nxtCookies = cookies();

    if (nxtCookies.has('session')) {
        const cookie = nxtCookies.get('session');

        let sessionData = jwt.verify(cookie.value, process.env.ACCESS_TOKEN_SECRET, (err, user) => {
            if (err) return false;
            return user;
        });

        if (sessionData) return sessionData;
    }

    return false;
 }
X33
  • 1,310
  • 16
  • 37

1 Answers1

3

While re-reading the Next.js docs, I missed this crucial part:

Invalidating the Cache: The cache can be invalidated using router.refresh(). For more information, see the API reference. In the future, mutations will automatically invalidate the cache.

Simply adding router.refresh() before my router.push() call fixed the problem.

X33
  • 1,310
  • 16
  • 37