Defer getServerSideProps on client-side navigation #32243
-
Feature requestIs your feature request related to a problem? Please describe.When clicking in a link to a page that uses Describe the solution you'd like
I should be able to opt-in this behavior with a flag in the return of // pages/example.js
function Post({ post }) {
const router = useRouter()
// If the page data is not yet fetched, this will be displayed
// initially until getServerSideProps() finishes running
if (router.isFetchingAfterDefer) {
return <div>Loading...</div>
}
// Render post...
}
export async function getServerSideProps(context) {
return {
props: { ... },
deferOnClientSideNavigation: true,
}
} Describe alternatives you've consideredUsing |
Beta Was this translation helpful? Give feedback.
Replies: 56 comments 56 replies
-
Hi function Index({ posts }) {
const [postsArr, setPostsArr] = useState(posts);
useEffect(() => {
async function fetchNewPosts() {
const res = await fetch("https://getpost.com/");
setPostsArr(await res.json());
}
if (posts.length === 0) {
fetchNewPosts();
}
}, []);
return (
<>
<Nav />
<p>Hello World May I Pick Banana!</p>
<pre>{JSON.stringify(postsArr, null, 4)}</pre>
</>
);
}
Index.getInitialProps = async ({ req }) => {
let posts = [];
if (req) {
const res = await fetch("https://getpost.com/");
posts = await res.json();
}
return { posts };
};
export default Index; in this approach if there is request we fetch data at first place (Server Side Rendering) but if we navigating to this page with |
Beta Was this translation helpful? Give feedback.
-
@sadraromexs That's exactly what I've done in my previous 2 NextJS projects. Since starting my new project I've taken the official advice and am doing everything using getServerSideProps (because I believe the current model for getStaticProps is totally broken). My old sites were lightning fast, the new one is significantly slower, because making a trip to the API on every request is obviously going to be slower. Seems like a bad decision. |
Beta Was this translation helpful? Give feedback.
-
It's obvious that user should not wait a few seconds in which nothing happens (because getServerSideProps is not finished loading) when he clicks a link. He should see some action is happening, for example:
Just one question, how then you will skip graphql parallel query with
|
Beta Was this translation helpful? Give feedback.
-
Any news on this issue? I'll be developing a project which has similar requirements soon and want to know whether to use |
Beta Was this translation helpful? Give feedback.
-
Same problem here. It’s my first NextJS app and I’m not sure how to handle this situation. I’m probably going to end up using |
Beta Was this translation helpful? Give feedback.
-
Still waiting to see what happens with this. They say that getInitialProps is still going to be supported but it's been heavily demoted in the documentation and my guess is that it will stay there but won't be worked on again (just a guess but seems reasonable). The trouble is, the more I think about this issues the more I think it's intertwined with other issues do do with Data fetching. GetStaticProps should also work this way (blocking when generating SSG, not blocking when client side navigation) and we hope to see improvements that allow data-fetching at app/path/component level not just page level. All of this is tied together and needs a solution which brings it all together. My hope would be that Vercel would open up an RFC for people to comment on a new props fetching solution where we can discuss all of these issues on one place and find a single solution. That's ot something for a minor release though. |
Beta Was this translation helpful? Give feedback.
-
The solution to this issue is covered by https://reactjs.org/blog/2020/12/21/data-fetching-with-react-server-components.html and it's interplay with concurrent mode / suspense. Can't share the exact details yet, will keep you posted. |
Beta Was this translation helpful? Give feedback.
-
Any activity on this? You really need to think about it. I don't understand why this issue takes so little attention from community... |
Beta Was this translation helpful? Give feedback.
-
FYI, |
Beta Was this translation helpful? Give feedback.
-
Couldn't agree with this more. There should be no server side call on client-side navigation. That should be the default way data-fetching works unless you opt out of it. It's especially annoying seeing as this was possible before (and technically still is if you're prepared to build a new site on deprecated features). |
Beta Was this translation helpful? Give feedback.
-
I really hope this feature is added because getServerSideProps is slowing down our site quite tremendously. Language used around getInitialProps makes it seem like it will be deprecated soon, and getStaticProps/Paths just doesn't make sense for our use-case because our pages have a lot of dynamic data, some of which depends on the user. |
Beta Was this translation helpful? Give feedback.
-
wow, i didn't realize how fast and convenient NuxtJS |
Beta Was this translation helpful? Give feedback.
-
It's not deprecated / will not be deprecated soon. We just recommend |
Beta Was this translation helpful? Give feedback.
-
@timneutkens how does this solve the majority of use cases since |
Beta Was this translation helpful? Give feedback.
-
Noted. That's good because we changed our implementation over to |
Beta Was this translation helpful? Give feedback.
-
I'm experiencing significant delay times in Next.js 10.0.3 (not 12 I know) on routing to dynamic routes such as It's a shame this is still a big issue and it's something I haven't come across before, strangely, being a long-time advocate of Next.js. |
Beta Was this translation helpful? Give feedback.
-
One and half year for this issue discussion. What about just add |
Beta Was this translation helpful? Give feedback.
-
Why look for new alternatives when one version before "getInitialProps" was already working great? We can always create a getServerSidePropsOnce by just reading a flag to determine whether getServerSideProps should be called internally. This discussion as @eseQ stated is going on for 1.5 years and the only progression is the limitation of i18n (deprecation of getInitialProps). Nevertheless, if we don't want to do more why not do what we were already been doing with getInitialProps in the first place? It's simple to me :) . |
Beta Was this translation helpful? Give feedback.
-
Hi everyone, Incase you missed it, we recently shared an RFC that includes new routing behavior: https://nextjs.org/blog/layouts-rfc There is likely some crossover with the points raised here and the conclusion where we discuss Instant Loading States (and possibly Offscreen Stashing with Instant Back/Forward).
We welcome any feedback here: #37136 |
Beta Was this translation helpful? Give feedback.
-
Hi, Is there anything new here. I wrote a lib to solve it if you https://github.com/Innei/next-suspense And you can try a demo. https://next-suspense-navy.vercel.app/ |
Beta Was this translation helpful? Give feedback.
-
I can't believe this undeniable problem is still not resolved. I came to Next for a project because Nuxt3 is not stable yet. After reading docs I realised that Nuxt2 even handled this way better When you have the |
Beta Was this translation helpful? Give feedback.
-
Currently we are using Next11 are there any work arounds to this problem? |
Beta Was this translation helpful? Give feedback.
-
Hope to hear of a resolution to this issue - absolutely butchering the performance of my SSR pages |
Beta Was this translation helpful? Give feedback.
-
It's been years and still no solution |
Beta Was this translation helpful? Give feedback.
-
The original problem proposed is now solved with the Next.js App Router (Next.js 13+). The root issue was wanting to fetch data on the server, but not block navigation. With improvements in React 18 and the new Next.js App Router, this is now possible using Instant Loading UI ( Clicking a link to a page that requires data to be retrieved on the server can immediately provide feedback to the user, showing an instant loading state, while the request (made inside an Async Component) can // app/loading.ts
export default function Loading() {
// You can add any UI inside Loading, including a Skeleton.
return <LoadingSkeleton />
} // app/page.js
// This is a Server Component by default
export default async function Page() {
const data = await getData();
return '...'
} Learn More |
Beta Was this translation helpful? Give feedback.
-
I found a hacky solution that monkey-patches This is better than the solution described in #32243 (comment) because it avoids the |
Beta Was this translation helpful? Give feedback.
-
Rather than mock the response in server side like #32243 (comment) did, I directly hijacked the export const useNextFetchHijacking = () => {
useEffect(() => {
const { fetch: originalFetch } = window;
window.fetch = async (...args) => {
const [resource] = args;
if (typeof resource === 'string' && resource.includes('_next/data')) {
return {
status: 200,
statusText: 'OK',
json: async () => ({ pageProps: {} }),
text: async () => JSON.stringify({ pageProps: {} }),
ok: true,
redirected: false,
headers: new Headers(),
type: 'basic',
url: resource,
} as any;
}
const response = await originalFetch(...args);
return response;
};
return () => {
window.fetch = originalFetch;
};
}, []);
}; It's pretty hacky as it only returns necessary data nextjs would use from the fetch response. It may break if nextjs updates to use other properties that are covered in mocked response. But normally it should be enough. |
Beta Was this translation helpful? Give feedback.
-
I implemented another solution. I did not want to use getInitialProps as it's considered legacy. We can use this helper to know if we are on the first initial load, or after in a client navigation. const isFirstServerCall = context.req?.url?.indexOf('/_next/data/') === -1; So what I'm doing is : Create a import { DehydratedState } from '@tanstack/react-query';
import { GetServerSideProps } from 'next';
type ServerSideResponse = {
dehydratedState?: DehydratedState;
};
export const onlyOnFirstServerCall = (
getServerSidePropsFunc: GetServerSideProps<ServerSideResponse>
): GetServerSideProps<ServerSideResponse> => {
return async (context: any) => {
const isFirstServerCall = context.req?.url?.indexOf('/_next/data/') === -1;
if (!isFirstServerCall) {
return {
props: {}
};
} else {
return getServerSidePropsFunc(context);
}
};
}; And on your page, this function will be used like a HoC : export const getServerSideProps = onlyOnFirstServerCall(async (ctx: any) => {
const queryObject = ctx.query;
...what you do normally
}); So you have the choice to enable it or not. |
Beta Was this translation helpful? Give feedback.
-
Tiny (1.4kb) library that allows you to patently execute/skip getServerSideProps/getStaticProps requests on soft navigation. Starters: That library allows you:
|
Beta Was this translation helpful? Give feedback.
The original problem proposed is now solved with the Next.js App Router (Next.js 13+).
The root issue was wanting to fetch data on the server, but not block navigation. With improvements in React 18 and the new Next.js App Router, this is now possible using Instant Loading UI (
loading.js
), React Suspense, and HTTP streaming.Clicking a link to a page that requires data to be retrieved on the server can immediately provide feedback to the user, showing an instant loading state, while the request (made inside an Async Component) can
await
the results needed.