nextjs reload page with Link component
Asked Answered
F

4

6

I have a simple nextjs 13 application (appDir) with 2 pages and a <Link/> component navigation.

  • first page Home - static
  • second page Test - receiving dynamic random content on the server side (fetch) from a third-party source.

Problem: When the application is rendered everything works fine, but when I try to switch between pages, my test page shows the old content, I can refresh the browser to get the actual data, is very similar to navigating through regular links <a/>, but i need without reloading the entire application.

Q: How can I force nextjs 13 to reload the Test page when I switch between pages with <Link/> component?

// src/components/navbar.tsx

'use client'

import {usePathname} from "next/navigation";
import Link from "next/link";

const navItems = [
    {text: 'Home', href: '/'},
    {text: 'Test', href: '/test'}
];

const Navbar = () => {
    const pathname = usePathname();

    return <nav className="nav nav-masthead justify-content-center float-md-end">
        {navItems.map((item: { text: string, href: string, link?: boolean }, idx: number) => (
                <Link key={idx} href={item.href} className={`nav-link${item.href === pathname ? ' active' : ''}`}>
                    {item.text}
                </Link>
            )
        )}
    </nav>
}

export default Navbar;
// src/app/test/page.tsx

import * as crypto from "crypto";

const getData = async () => {
    const res = await fetch('http://localhost:3000/random-data', {cache: 'no-store'});
    if (!res.ok) {
        throw new Error('Failed to fetch data');
    }
    return res.json();
}

export default async function Page() {
    return <p>{crypto.createHash('sha256').update(JSON.stringify(await getData())).digest('hex')}</p>
};

Flatworm answered 22/12, 2022 at 4:24 Comment(1)
How are you navigating form home to TestWurth
G
6

I've recently asked about this same topic on their feedback discussion on github: https://github.com/vercel/next.js/discussions/41745?sort=new#discussioncomment-4620262

The cause of the problem is Link is only doing client side navigation and seems to serve a cached state of the previously visited component. You'll notice that the client never calls back to the server and thus the server component never runs the second time.

I've been searching for days, but haven't found a way to force Link to reload or force refresh the component to re-render.

My conclusion is that if you have dynamic data that needs to refreshed periodically, it's best to render it in a client component and not use a server component for now.

Also, if you'd like to use Suspense, you'll need to use a library like SWR or React Query for any client side data fetching.

Greenaway answered 10/1, 2023 at 4:12 Comment(0)
I
0

One workaround that seems to work is to include a client side component on the SSR layout template page, forcing a refresh on mount.

At first it seemed it would cause an infinite refresh loop, but it is testing fine. Only issue is an extra refresh on page nav.

// Sample Refresher Component
// to be imported into SSR page
// needing a refresh after 
// next.js appDir Link nav
//
// tested in next.js 13.2.3

'use client'
import { useRouter } from 'next/navigation'
import { useEffect } from 'react'

export function Refresher() {
    const router = useRouter()

    useEffect(() => {
        router.refresh()
    }, [router])

    return <></>
}
Interest answered 9/3, 2023 at 18:19 Comment(0)
G
0

I think it would be beneficial to try to update a component (or components) and not the entire page.

So, make the Test page render multiple components, some server (that can just be static content) and some dynamic with 'use client'. It should be the case now where the client components can use the client hooks within themselves and only update/re-render themselves when needed.

Simply, break up your page into components.

Gosling answered 27/6, 2023 at 2:9 Comment(0)
B
0

If you really want to use the Link component then I'll suggest either the use of useState or useEffect to fetch the latest data while using the old data as the initial data

Badillo answered 23/6 at 14:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.