Next.js Discord

Discord Forum

Server Component Data Fetching on each request

Unanswered
sudo posted this in #help-forum
Open in Discord
Hello,

I'm in the app directory, and i have a page for the /account route, (src/app/account/page.tsx)
Basically, i am fetching data serever-side, and based on that data we decide what to render to the client. The question here is the way to navigate to this page, is either via <Link> or a router.push using useRouter from (next/navigation), this to keep the SPA-like aspect of the page, and not cause the states to re-render.
But it looks like this page is getting cached whenever we use these methods, and the data-fetching is not occurring on each request. How can i make it occurr on each request?
The function below fetchDataServerSideBeforeRenderingPage() is an axios fetch operation with 'Cache-Control': 'no-store' header.

This is the code of the page that is being rendered on the server:

'use server' import React from 'react'; import fetchDataServerSideBeforeRenderingPage from '@/app/..'; async function AccountPage() { const data = await fetchDataServerSideBeforeRenderingPage(); if (data){ return ( <> <h1>Access Granted </h1> </> ) } else { return <h1>Unauthorized Access</h1>; } } export default AccountPage

81 Replies

I tried using a router.push() followed by a router.refresh() as a workaround, but i think this could cause race conditions.
Also, i tried using revalidatePath(), beforep pushing to the path, but this will cause two renders (two data-fetches).
via <Link> or a router.push using useRouter from (next/navigation), this to keep the SPA-like aspect of the page, and not cause the states to re-render.
But it looks like this page is getting cached whenever we use these methods, and the data-fetching is not occurring on each request. How can i make it occurr on each request?
You can disable prefetching on your <Link>
also remove this
@ᴉuɐpɹɐɐ > via <Link> or a router.push using useRouter from (next/navigation), this to keep the SPA-like aspect of the page, and not cause the states to re-render. > But it looks like this page is getting cached whenever we use these methods, and the data-fetching is not occurring on each request. How can i make it occurr on each request? You can disable prefetching on your <Link>
Hey, even if i disable prefetch, the data appearing will still be stale data.
What i am trying to achieve here is exactly what we had in the pages router where we used getServerSideProps.
So basically, the behavior needed is to fetch data on each visit to this /account route. On each request. And for it to be rendered on the server.
Its weird how i can't find anything about this issue online and no one knows anything about it :/
Also, i want to keep the 'use sever' statement, to make sure that the component is explicitly rendered on the server
@sudo Also, i want to keep the 'use sever' statement, to make sure that the component is explicitly rendered on the server
the "use server" is not for ensuring it is rendered on the server.
You are looking for import "server-only"
@ᴉuɐpɹɐɐ the "use server" is not for ensuring it is rendered on the server. You are looking for `import "server-only"`
yep, i tried using import 'server-only' with a 'use server' for a file that has functions intended to run on the server, for some reason they do not work together :/
@sudo yep, i tried using import 'server-only' with a 'use server' for a file that has functions intended to run on the server, for some reason they do not work together :/
im sorry i dont address the real issue but "use server" is not used to make function run on the server. "use server" will create an endpoint in your next.js server which is why its not advisable to be used as a directive "to make stuff only run in the server"
A Server Action can be defined with the React "use server" directive. You can place the directive at the top of an async function to mark the function as a Server Action, or at the top of a separate file to mark all exports of that file as Server Actions.
yes, its to make "Server Actions" which are different from "function that is only used in the server"
Doesn't a server action create an endpoint, and this endpoint runs a specific logic (Function). So it's actually a server function, no ?
Server Actions are server endpoints that is accessed via the client, if you only used them in server environment then its better to not use Server Action
is what im saying
Okay..
my question here if i want a page to be rendered on the server, it shouldn't have a 'use server' on top of it?
the same way i added in this example
This marks it as a Server Component
something different from server actions
Assume AccountPage is a server component, then fetchDataServerSideBeforeRenderingPage is just a regular async function. if its not used in the client component (or <form>) then it doesnt have to use "use server" on it
aha
if i want a page to be rendered on the server, it shouldn't have a 'use server' on top of it?
yes.
page.jsx and layout.jsx are by default server component.

then the determination of server and client is decided from the root file (page.js/layout.js)
okay, since page.tsx is by default a server component, adding a 'use server' is the same, no ?
My question here is, how do i get fetchDataServerSideBeforeRenderingPage() function to run each time this /account page is navigated to. (Using <Link> or a useRouter navigation). That was the problem here
Also, if page.tsx is by default a server component, then adding 'use server' to it won't change anything
yeah but it is exposing whatever async component as an endpoint.. which is obscured, technically accessible for anyone. could be a security concern.

But it looks like this page is getting cached whenever we use these methods, and the data-fetching is not occurring on each request. How can i make it occurr on each request?
This is because the client side navigation keeps a local (per browser) cache that lasts for 30s after your last navigation.

The client-side caching configuration is still in beta right now (undocumented) but you can try
const nextConfig = {
  experimental: {
    staleTimes: {
      dynamic: 0, // set this to 0
      static: 180,
    },
  },
}
theres also one other option, which is to use useEffect to call the data fetching every "component mount" which is automatically handled by React Query. This is however, less than ideal as it could get spammy (though hard to get it right with proper configuration) and even harder to implement with raw useEffect
"use server" basically makes all the exported async component as a public endpoint. even if its obsecure, someone could theorhetically access whatever exported in that file directly (without accessing the page). This makes it hard to control.

Not to mention that all exported funciton get automatically converted to async function (even if you dont use async) which is why its worse for consistency
its just that you used something thats not what its designed for, i just want to ensure consistencies in your code base
wow
okay
i will take a look at that
I agree the names are confusing so im just trying to not blame you for it
now how can i implement this /account page to be a protected route in NextJS then and rendered on the server?
you should prioritise on the import "server-only" and if you have any import errors it must be that you imported a "server-only" file to a client component (reminder: this doesnt mean component that ONLY uses "use client", other component that suddenly becomes client component can also cause this error)
if you have a function that can be used in both server and client, its better to move it away from import "server-only"
move it away: move it into a new file
basically what i am doing is the following:
Frontend: NextJS 14 - React
Backend: ExpressJS - MongoDB
Im having hard time with authentication, protected pages ...
basically all requests should be validated on the backend
so what i want to have in /account is a server side rendered component, that will call the backend to make sure this session should access this page or no
and all of this should be done on the server, away from the client
yes
you can make a function that checks your express backend that is marked with "server-only".
this way you 100% ensure this function wont run in the client.
easy as that
fetchDataServerSideBeforeRenderingPage() i will make this an import server-only function
i wouldnt make my guaranteed server component (like page.js or layout.js) with "server-only" but thats just preference
@ᴉuɐpɹɐɐ i wouldnt make my guaranteed server component (like page.js or layout.js) with "server-only" but thats just preference
if i remove the 'use server' from page.tsx (/account), and run the function that is import server-only here to make sure that this session has access to this endpoint, this will be good security-wise, right?
and since you mentioned page.tsx is by default server-side rendered, everything will happen server-side
it will break your entire app if your "server-only" funciton are accidentally imported to your client-component and you will notice it at development. Since its handled via bundling and not by programmatic logic
tsc won't catch that?
no
idk maybe
but it will break your entire app, which is good enough coz you really cant import it to client-js
lol
@sudo and since you mentioned page.tsx is by default server-side rendered, everything will happen server-side
yes. if you dont believe this, add console.log() in your component and see where it gets logged
its also in the docs
sometimes i think life was much better in the pages router
i havent used the "server-only" in a while but last time i used it, it prevents me from importing the function to client-js.

It even works if its like not a direct import

if funcA has "server-only"
and funcB imports funcA, separate file, doesnt have "server-only"

and (client) func C imports funcB, it will throw an error
yes, they get nested somehow 🙂
@sudo sometimes i think life was much better in the pages router
its much easier not because its "pages" router, but because of the paradigm that we are moving away from. The old way feels better because the entire thing is a (server rendered) client component.

Not as good if we want a server-rendered components that is still beautifull even if we disable javascript
the new paradigm that we're moving into is the harmonization of server and client. It can be a more efficient space, at the cost of more complicated paradigm
exactly
we should have a well documentated page about everything that is use server, server actions, server functions etc...
one spot, to read everything
before exploring
not like the next docs, it is somehow overwhelming
i hope they improvve it
or at least add this section
omw
but ultimately this is React's feature not Next.js's
yes
you can find this "paradigm" in more and more framework too,
Redwoodjs
waku,
hono..
and more coming soon
maybe this needs to be more clear specifically what part of "next.js" that is defaulted to "Server Component"
yes