Next.js Discord

Discord Forum

Server-side component not re-rendering when navigating with next link

Unanswered
Sloth bear posted this in #help-forum
Open in Discord
Sloth bearOP
I got a server side component that fetches from a api, the fetch is set to no cache.
When I navigate to the page with the component in it with next link, the fetch isn't exectued again.
When I navigate directly to the route throught the address bar the fetch is executed and I get the current data.
Why is that behaviour?
THI 🙏
// admin/settings/page.tsx
import OverviewTable from "@/components/admin/settings/overview-table";

export default async function Page() {
  return (
    <>
      <h1>Settings</h1>
      <p>
        Welcome to the admin page.
      </p>

      <OverviewTable />
    </>
  );
}

// components/admin/settings/overview-table
export default async function OverviewTable() {
  async function fetchValue() {
    const data = await fetch("http://localhost:3000/api/value", {
      next: { tags: ["value"] },
      cache: "no-store",
    });
    const values = await data.json();
    return values;
  }
  const values = await fetchValue();

  return (
    <table>
//ofc here the values are maped, etc... 
//i just simplified for the sake of ease
      {values}       
    </table>
  );
}

38 Replies

Do you show something different over time in the same page?
What you are saying sounds like full route cache
Sloth bearOP
This component is a table that shows "values". I can change properties of these "values"
if you mutate your db, you need to revalidate cache using revalidatePath or revadliateTag
Sloth bearOP
I do revalidateTag at the api endpoints:
// api/value/[slug]/nominee/[id]/route.ts

export async function POST(request: any, { params }: any) {
  const { short, id } = params;
  try {
    const response = await addNominee(short, id);
    revalidateTag("value");
    return NextResponse.json(response);
  } catch (error) {
    console.error(error);
    return NextResponse.json({ message: "Error", error }, { status: 500 });
  }
}

export async function DELETE(request: any, { params }: any) {
  const { short, id } = params;
  try {
    const response = await removeNominee(short, id);
    revalidateTag("value");
    return NextResponse.json(response);
  } catch (error) {
    console.error(error);
    return NextResponse.json({ message: "Error", error }, { status: 500 });
  }
}
try unstable_noStore() then
Sloth bearOP
But I think the caching of the fetch isn't the problem here:
When I do a hard reload the terminal prints:
GET /admin/settings 200 in 128ms
 │ GET http://localhost:3000/api/value 200 in 62ms (cache skip)
 │ │ Cache skipped reason: (cache: no-store)

but when using the navigation it prints nothing
I also when I tried with a console log in the component it only got logged after a manual refresh and not when navigating.
hmm that's full route cache
which version of Next.js are you using? @Sloth bear
wait wait @Sloth bear
const data = await fetch("http://localhost:3000/api/value", {
      next: { tags: ["value"] },
      cache: "no-store",
    });
are you running your next.js on 3000 port?
Sloth bearOP
yes I am
well the dev atleast
@James4u are you running your next.js on 3000 port?
Sloth bearOP
why would that matter?
in server component, you shoudn't call your route handlers
you should move the logic directly to your server component
@James4u you should move the logic directly to your server component
Sloth bearOP
I should move the db call to my server component 🤔
@James4u https://nextjs-faq.com/fetch-api-in-rsc
Sloth bearOP
good that I moved my whole fetchin to the api route because I thought that would fix my problems 🙈
but will this fix my problem? and how do I fetch data in client components?
if you have to fetch data from client component, you need api routes
some people use server actions for data fetching - personally I don't like this but you can use if you dont mind
Sloth bearOP
so you would call f.e addNominee(short, id); in ss pages and components and the api in cs?
like create a function (server action) which queries db or fetch data from 3rd party
and use can use it inside your server component
and also you can use it in your client component with react-query
Sloth bearOP
I am going to try that out tomorrow, enough for today ;)
Let's see if it is going to work, thx already
@Sloth bear any good luck?
@James4u <@707150454819389511> any good luck?
Sloth bearOP
Haven't finished yet.
Sloth bearOP
Hey @James4u
I was finally able to fix it, partially.
My interactive components are now client-side and trigger a handleSubmit action. The db fetch then call revalidatePath before returning the values.
The problem is that there is an other page(ssr) with a component(ssr) which has the same values. This component won't show the new values eventough I revalidatePath the page.
Sloth bearOP
@James4u
my-app/
├─ public/
├─ src/
│ ├─ app/
│ │ ├─ settings/
│ │ │ ├─ page.tsx
│ │ │ ├─ [slug]/
│ │ │ │ ├─ page.tsx
│ ├─ components/
│ │ ├─ settings/
│ │ │ ├─ Table.tsx
│ │ │ ├─ [slug]/
│ │ │ │ ├─ Table.tsx
│ │ │ │ ├─ AddNominee.tsx
│ │ │ │ ├─ RemoveNominee.tsx

I hope this helps
so what I wanted to say is the settings/Table.tsx and page is ssr and they call a server action to get data.
the /slug/AddNominee and RemoveNominee are csr and call a server action to get data.
the server actions addNominee and removeNominee both call revalidatePath("/settings"); and revalidatePath("/settings/[slug]", "page");
the settings/[slug]/Table does show the changes immediately but the the /settings/Table doesn't in build. In dev server everything works fine