skip to Main Content

So I’m in the process of learning/adapting to NextJS 13 with its new APP folder. I’m having a hard time figuring out how to update data on server components without having to reload the page/app.. Currently my HomePage server component fetches a list of items (events) from MongoDB. 

If from behind the scene I change the DB data and then navigate to another route on my app and back to the HomePage without reloading, the new data is not displayed. It’s only displayed if I hard reload the page directly from the browser. The same goes for my EventDetails component. If I change one of the event’s data directly on the database after loading the app in the browser, that change is not displayed in the app when I navigate to that event’s detail unless I directly reload the page.


I have set the following option in the fetch function


catch: 'no-cache'
next: { revalidate: 1 },



And also tried settings this exports in the component file


export const revalidate = 0;
export const dynamic = 'force-dynamic'

;




But still its not updating the values.

Here is my full code.

// HomePage Component (app/page.jsx)
import React from 'react';
import MeetupList from './_components/meetups/meetupList';
export const revalidate = 0;
export const dynamic = 'force-dynamic';

const fetchMeetups = async () => {
  const response = await fetch('http://localhost:3000/api/meetup', {
    catch: 'no-cache',
    next: { revalidate: 1 },
  });

  const data = await response.json();

  return data;
};

const HomePage = async () => {
  const meetups = await fetchMeetups();
  return (
    <>
      <MeetupList meetups={meetups} />
    </>
  );
};

export default HomePage;


//MeetupList.jsx
import MeetupItem from './MeetupItem';

import styles from './MeetupList.module.css';
export const dynamic = 'force-dynamic';

function MeetupList({ meetups }) {
  return (
    <ul className={styles.list}>
      {meetups.map((meetup) => (
        <MeetupItem
          key={meetup._id}
          id={meetup._id}
          image={meetup.image}
          title={meetup.title}
          address={meetup.address}
        />
      ))}
    </ul>
  );
}

export default MeetupList;

Is this something I have to do with the new Server Action which I believe is still in Beta Mode?

Thanks

CES

2

Answers


  1. Official Documentation says

    By default, all fetch() requests are cached and deduplicated automatically. This means that if you make the same request twice, the second request will reuse the result from the first request.

    Requests are not cached if:

    • Dynamic methods (next/headers, export const POST, or similar) are used
      and the fetch is a POST request (or uses Authorization or cookie
      headers)
    • fetchCache is configured to skip cache by default
    • revalidate:
      0 or cache: ‘no-store’ is configured on individual fetch

    So why don’t you try something like that

    const HomePage = async () => {
      const res = await fetch('http://localhost:3000/api/meetup', { next: { revalidate: 0 } })
      const meetups = res.json()
    
      return (
        <>
          <MeetupList meetups={meetups} />
        </>
      )
    }
    
    Login or Signup to reply.
  2. Apparently, this is a long-standing issue in Next 13. Please see the following ticket dating back to Nov 2022 and feel free to upvote.

    https://github.com/vercel/next.js/issues/42991

    You can find numerous workarounds in the above thread (some of them no longer work though). Please see which one works best in your case, but here is a workaround I’m using for now:

    // components/Link.tsx
    
    "use client";
    
    import { ComponentProps, forwardRef } from "react";
    import NextLink from "next/link";
    import { useRouter } from "next/navigation";
    
    export default forwardRef<
      HTMLAnchorElement,
      Omit<ComponentProps<typeof NextLink>, "href"> & {
        href: string;
        refresh?: boolean;
      }
    >(function Link({ href, onClick, refresh, children, ...rest }, ref) {
      const router = useRouter();
    
      return refresh ? (
        <a
          ref={ref}
          href={href}
          onClick={(event) => {
            onClick?.(event);
            if (!event.defaultPrevented) {
              event.preventDefault();
              router.push(href);
              router.refresh();
            }
          }}
          {...rest}
        >
          {children}
        </a>
      ) : (
        <NextLink ref={ref} href={href} onClick={onClick} {...rest}>
          {children}
        </NextLink>
      );
    });
    
    // test/page.tsx
    
    import Link from "@/components/Link";
    
    <Link refresh href="/">Home</Link>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search