Next.js Discord

Discord Forum

Server code with App Router and server components

Unanswered
Netherland Dwarf posted this in #help-forum
Open in Discord
Netherland DwarfOP
Hey there, i've got some trouble with server components, how can i trigger server code each time i render a component ?

export default async function Page() {
  console.log("this code is running only when i'm hard refreshing !");

  return <></>;
}

export const revalidate = 1;

43 Replies

fret not since client components are still as powerfull as server components. Its SSR'd and you have nothing to be discouraged for when using it
Netherland DwarfOP
Yeah but it seems clashing with what it said in the doc about dynamic rendering : https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic

Even if it works with client component, i've got some weird things going on with cookies...

I tried to tweak it like this :
import { cookies } from "next/headers";
import uid2 from "uid2";

export default async function Page() {
  const token = cookies().get("token")?.value;

  const random = uid2(20);
  const res = await fetch("http://localhost:3000/api?q=" + random, { cache: "no-store" });
  const data = await res.json();

  const random2 = uid2(20);
  const res2 = await fetch("http://localhost:3000/api?q=" + random2, { cache: "reload" });
  const data2 = await res2.json();

  return (
    <div>
      <p>{random}</p>
      <p>{random2}</p>
      <p>{token || "no token"}</p>
      <p>{data}</p>
      <p>{data2}</p>
    </div>
  );
}

export const revalidate = 1;

Then my route handler is here :
export async function GET(request: NextRequest) {
  console.log(request.nextUrl.searchParams.get("q"));

  const token = cookies().get("token")?.value; // This is undefined but i've got a "token" cookie in my browser

  c.set("randomCookie", uid2(12)); // This does not set any cookie in the browser

  const msg = JSON.stringify(uid2(12));

  revalidatePath("/private/profile");

  return new Response(msg, { status: 200, headers: { "Content-type": "application/json" } });
}


Maybe as you said i'm trying to overuse server components, or maybe i'm misunderstanding the doc 😦
@Netherland Dwarf Yeah but it seems clashing with what it said in the doc about dynamic rendering : https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic Even if it works with client component, i've got some weird things going on with cookies... I tried to tweak it like this : tsx import { cookies } from "next/headers"; import uid2 from "uid2"; export default async function Page() { const token = cookies().get("token")?.value; const random = uid2(20); const res = await fetch("http://localhost:3000/api?q=" + random, { cache: "no-store" }); const data = await res.json(); const random2 = uid2(20); const res2 = await fetch("http://localhost:3000/api?q=" + random2, { cache: "reload" }); const data2 = await res2.json(); return ( <div> <p>{random}</p> <p>{random2}</p> <p>{token || "no token"}</p> <p>{data}</p> <p>{data2}</p> </div> ); } export const revalidate = 1; Then my route handler is here : tsx export async function GET(request: NextRequest) { console.log(request.nextUrl.searchParams.get("q")); const token = cookies().get("token")?.value; // This is undefined but i've got a "token" cookie in my browser c.set("randomCookie", uid2(12)); // This does not set any cookie in the browser const msg = JSON.stringify(uid2(12)); revalidatePath("/private/profile"); return new Response(msg, { status: 200, headers: { "Content-type": "application/json" } }); } Maybe as you said i'm trying to overuse server components, or maybe i'm misunderstanding the doc 😦
you can just put the route handler logic directly in Page() server component
but server components are only run when the component needs building such as request to dynamic route renders, or at static build\
Netherland DwarfOP
It says i have to use "cookie.set" inside a route handler or a server action
if you really want to ensure running server code at component mount then, the use of client component using useEffect() is necessary
Netherland DwarfOP
And i don't know why the route handler is not seeing my token...
Even in the component code, somehow sometimes the cookie get deserialized with a value of "" instead of the right value, or just undefined that's so weird.
Netherland DwarfOP
I'm gonna do some other test with useEffect 🤔
Netherland DwarfOP
Okay, so cookies are working fine with client component that's good new 😛
As i got you i've got few questions more :
export async function GET(request: NextRequest) {
  redirect("/");
}

Seems like "redirect" is not working at all 🤔, no matters if i call it from client or from server and i quote the doc :
The redirect function allows you to redirect the user to another URL. redirect can be used in Server Components, Client Components, Route Handlers, and Server Actions.

So i take the "useRouter" hook in the client component and redirecting depending of the route handler response :
"use client";

import ServerComponent from "@/components/auth/authChecker/AuthChecker";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import uid2 from "uid2";

export default function Page() {
  const router = useRouter();

  useEffect(() => {
    const f = async () => {
      const res = await fetch("/api");
      const data = await res.json();
      console.log(data);
      // router.push("/");
    };
    f();
  }, [router]);

  return (
    <div>
      <ServerComponent /> {/* Any problem with doing this ? */}
    </div>
  );
}

Does it seems okay for you ?
yeah redirect() is for server side stuff only
idk why it says client components 🤔
Netherland DwarfOP
You mean i can wrap server component into a context provider but not return it in the CC's JSX ?
you can but its just an antipattern
unless its just a generic noninteractive server-function-absent components
since SC imported into CC will be regarded as CC and stuff WILL break if you put server-function in there
since server-function can't be run in the browser
Netherland DwarfOP
Oh yeah okay that's a huge point
So wrapping into {children} is fine
yep fyi, the SC nested inside CC will be sent to browser as JSON and will be populated whenever the parent client component is ready to render
so prerendering still works
and if CC is configured properly, SEO wont be affected
Netherland DwarfOP
Oh okaaaay that's explain a lot
About how i can balance client and server stuff
generally the best approach is put stuff that you want at initial render to the server
then delegate runtime interaction with client components
this includes navigation
coz routes are cached in client-side for 30s and if you really want INSTANT data update per component mount, you HAVE to use client components to manage your stale data
but if 30 second staleness is ok, then just go on about your daily life xD
Netherland DwarfOP
Seemed to me like Nextjs wanted to provide another paradigm, restless, stateless app with server action/revalidation, do you think it is what is planned for the future ?
i think thats the current design philosophy
idk about the future lol
Netherland DwarfOP
Haha okay, the mindset to use SC is a bit hard to get and i'm wondering how all of this will eventually change/break.
You helped me a lot ❤️
There's still some mysteries about server side function that does not behave like i expected (from the knowledge of the doc, like the redirect case) but i guess i can use it with less frustration now and that really a lot.
Big kiss to you ❤️ ❤️
to me SC are just a function that generates HTML codes that can be extended with Client Components to provide runtime interactivity
and is a one way function unlike Client Components, which can be run multiple times per render
Netherland DwarfOP
Yeah ok that's makes sense 🤔
@Netherland Dwarf Hey there, i've got some trouble with server components, how can i trigger server code each time i render a component ? tsx export default async function Page() { console.log("this code is running only when i'm hard refreshing !"); return <></>; } export const revalidate = 1;
Forest bachac
Hey all you gotta do is try getting cookies or call a dynamic fetch (no cache) or a third party lib fetch, and then it won't run that code afer that at build time and it'll turn it into a dynamic function that'll run each time.
I did a bunch of tests on this too, but I was only testing with console.log so it didn't trigger the next magic lol
also I might be wrong but I think export const revalidate = 1; has to go at the top of the page?
@Forest bachac Hey all you gotta do is try getting cookies or call a dynamic fetch (no cache) or a third party lib fetch, and then it won't run that code afer that at build time and it'll turn it into a dynamic function that'll run each time. I did a bunch of tests on this too, but I was only testing with console.log so it didn't trigger the next magic lol
Simply doing export const dynamic = 'force-dynamic' will turn the route into a dynamic route.

However that is not the issue here.
Dynamic route are still cached in the client for around 30 second from last interaction.
OP wants to run server code as soon as the component mount which may still fall under the 30 second client cache time.

Yes console.log should be enough to test out if a server component is rerendered
and no, export const revalidate doesn't need to go at the top of the page.