-
Notifications
You must be signed in to change notification settings - Fork 27.6k
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Defer getServerSideProps on client-side navigation #13910
Comments
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 |
@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. |
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
|
Any news on this issue? I'll be developing a project which has similar requirements soon and want to know whether to use |
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 |
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. |
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. |
Any activity on this? You really need to think about it. I don't understand why this issue takes so little attention from community... |
FYI, |
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). |
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. |
wow, i didn't realize how fast and convenient NuxtJS |
It's not deprecated / will not be deprecated soon. We just recommend |
@timneutkens how does this solve the majority of use cases since |
Noted. That's good because we changed our implementation over to |
I've found A good use case for You'll miss out on the automatic prefetching if you just use |
Hello everyone 👋 I was facing this problem in my project and I ended up using this as a workaround (hacky as hell but seems to work): const isServerReq = req => !req.url.startsWith('/_next');
function Post({ post }) {
// Render post...
}
export async function getServerSideProps({ req }) {
const initData = isServerReq(req) ? await fetch(...) : null;
return {
props: {
initData,
},
}
} |
Thanks god I found this thread.. I'm using NextJS since the beginning (> 3yr) and always upgraded with the new versions to get the new features. I'm using other libraries like next-routes, next-redux-wrapper, next-i18next and I cannot upgrade all of them anymore. I did all the work to migrate from getInitialProps to getServerSideProps for my SaaS and getStaticProps for the website but the result is just not what I was expecting. The fact that getServerSideProps is called on every client side routing is just a no go. At the end I felt like NextJS was just a nice solution for e-commerce and blogs but was not the solution to create a complex app because the current 3 methods (SSR/Path/Static) just don't answer the issue that getInitialProps alone was doing perfectly. I would prefer focusing on my features instead of reading all the possible discussions (GitHub/SO/Reddit) to find workarounds that should be normal behaviour (or at least fallback). Because of the doc, the other libraries are just like "getInitialProps will be removed soon so we will just stop supporting it at all now" (from the libraries owners). It's really annoying because we really want to migrate and get the new features but since v10 we got some regressions related to general use cases so we cannot fully enjoy the optimizations or update others libraries. I'll keep getInitialProps for now but I'll also keep my refactor branch active, waiting for news about a real SSR. I'm sure you have everything in the NextJS core to do something great though. Please don't only focus on blog/e-commerce, there are plenty of great/complex app that need the most advanced features of SSR! 🙏 |
That's good to know. But I think we'd all be interested to know why you're pushing the slower, less efficient new way of doing things for "the majority of use cases" when the old way is much faster? What benefit do we get from doing a server side call on every client-side navigation? Isn't there a way of changing it to get the best of both worlds? It seems that the team are quite dismissive of people's concerns over this and maybe don't understand the problem? |
Based on this reply, I've come up with a high order function to handle this in a more elegant way: /**
* Do not SSR the page when navigating.
* Has to be added right before the final getServerSideProps function
*/
export const hasNavigationCSR = (next?: GetServerSideProps) => async (
ctx: GetServerSidePropsContext,
) => {
if (ctx.req.url?.startsWith('/_next')) {
return {
props: {},
};
}
return next?.(ctx)!;
}; And I add this to all my pages: function getProps(ctx) {
// my logic
}
export const getServerSideProps = hasNavigationCSR(getProps); Been using high order functions to features that I need to attach to a page, such as authorization, translation, initializing apollo client, etc. It's a workaround, but works well and looks elegant with the other features: If anyone doesn't want to wait for an official implementation, like me, that's what I'd recommend. |
A similar approach to the above "solution" by adding import { curry } from 'lodash/fp';
const gSSPWithCSRFlag = curry((gSSP, context) => {
if (gSSP && context) {
// Set a flag to context that checks if the request
// is coming from client side routing/navigation
context.isCSR = Boolean(context.req.url.startsWith('/_next'));
return Promise.resolve(gSSP(context));
}
throw Error('Either context or gSSP is not provided');
});
export default gSSPWithCSRFlag; export const getServerSideProps = gSSPWithCSRFlag(async ({ isCSR, ...restCtx }) => { ... |
I'm still facing this problem, currently my project using May be the best solution for now: still using |
@nghiepit i'm facing this problem and using |
Since we know when a route change starts and completes I don't see how this is a problem. import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';
const useRouteChange = () => {
const router = useRouter();
const [routeChanging, setRouteChanging] = useState(false);
const handleRouteChangeComplete = () => setRouteChanging(false);
const handleRouteChangeStart = () => setRouteChanging(true);
useEffect(() => {
router.events.on('routeChangeComplete', handleRouteChangeComplete);
router.events.on('routeChangeStart', handleRouteChangeStart);
return () => {
router.events.off('routeChangeComplete', handleRouteChangeComplete);
router.events.off('routeChangeStart', handleRouteChangeStart);
};
}, [router]);
return { routeChanging };
};
export { useRouteChange }; Then a Spinner component: const Spinner = () => {
const { routeChanging } = useRouteChange();
const [shouldShowSpinner, setShouldShowSpinner] = useState(false);
const timer = useRef<NodeJS.Timer>();
useEffect(() => {
if (routeChanging) {
// Only show spinner on page loads taking longer than 100ms.
timer.current = setTimeout(() => setShouldShowSpinner(true), 100);
} else {
setShouldShowSpinner(false);
if (timer.current) {
clearTimeout(timer.current);
}
}
}, [routeChanging]);
if (!shouldShowSpinner) {
return null;
}
return spinner component here; Then in say const App = ({ Component, pageProps }: AppProps) => (
...
<Component {...pageProps} />
<Spinner />
...
); I use a timeout to only show the spinner on pages taking longer than 100ms, but if you want to show the spinner on every navigation the logic gets even simpler! With this we get SSR without page reloads, and the user gets feedback when pages are loading. For me what's missing is preloading of getServerSideProps data, just like with getStaticProps. @timneutkens, do you know if this is in the pipeline? I haven't look at the code for next/link yet, if this is something that could be merged I might open a pull request! Edit: |
any updates on this issue? |
Hi All, any updates on this issue? do we have any alternative to achieve this functionality? |
Hey guys. Any update about this? I have a similar use case with firebase/firestore. I Want to query it with firebase-admin server side, but with regular firebase client on the client side. This feature seems missing and is necessary to do proper SSR IMHO. |
Im coming from CRA just months ago, and I must say I didn't realize how fast CRA is until I converted the App to NextJS (From a complex Web App point of view). |
This comment has been minimized.
This comment has been minimized.
Hi, any update on this? |
i don't believe why this important issue should last this long :( |
i think this new patch can solve this problem https://github.com/vercel/next.js/releases/tag/v11.1.2 |
How Exactly ?? can you describe ? |
I'm sorry, my mistake :))) |
@Kyoij |
Also looking for the solution to use |
I wrote a proposal/RFC for an server-side only version of I'm working on a working prototype too, will share when ready. |
One of the main issue is still not resolved. This delay b/w clicking and actual navigation is one of the biggest flaw in UX dictionary. Any impatient user may click several time as there is zero response on frontend side (even the link takes time to change) Tried to bypass getSeverSideaProps by checking the request link but still that small delay exist because, a page having serverSideProps function must call that function before the actual navigation (that's annoying) They should provide some workaround in Link component (like shallow prop does - but shallow prop work for the links within the same page), so a developer would be able to bypass that function call from navigation cycle (click -> getServerSideProps() -> page load) |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
Feature request
Is your feature request related to a problem? Please describe.
When clicking in a link to a page that uses
getServerSideProps
, the navigation will be kept in hold until the server response is complete, then the navigation will start. I want to be able to defer thegetServerSideProps
data-fetching until the client-side navigation has been completed. Similar to the behavior ofgetStaticProps
withfallback: true
.Describe the solution you'd like
gSSP
request should be fired to fetch the content and send it through the page props.I should be able to opt-in this behavior with a flag in the return of
gSSP
. The router should have a flag to tell if the page is fetching data:Describe alternatives you've considered
Using
getInitialProps
/getServerSideProps
to detect if it is client-side navigation and send empty props, then repeat the fetch logic in the component codeThe text was updated successfully, but these errors were encountered: