I'm looking for solutions for better data fetching in a Next.js app. In this question I'm not just looking for a solution, I'm looking for multiple options so we can look at the pros and cons.
Right now I have a few pages that all include a component that displays som static content and a that have some dynamic content that is fetched from an API. Each page do a fetch()
in their getInitialProps()
to get their own page data, but also the footer data, which is the same for all pages.
This of course works, but there is a lot of duplicated data fetching. The footer data will always be displayed for all pages and always be the same. It will also rarely be changed in the API, so no need for revalidate the data.
I'm not just looking to solve this one problem, I'm looking for an overview to learn some new practice for future projects as well. I like writing "obvious" code, so not looking for too hacky solutions, like writing to the window
object etc. Simple solutions with less dependancies are preferred. The goal is a fast site. It's not that important to reduce network usage/API calls.
This is the possible solutions I've come up with, somewhat sorted from simple/obvious to more complex.
getInitialProps()
and add it to props, so data is available for all pagesAll of these "work", but most of them will refetch the data unnecessarily, and/or adds a bit more complexity. Here are the pros/cons as I see it (numbers are the same as above):
getInitialProps()
.fetch()
calls after each other (first in _app.js to load footer content, then in each page to get custom content), so it's even slower. rel="preload"
prefetching technique won't work with all types of fetching (for instance Sanity's client using groq). To not have "jumpy" content where the data is loaded after initial page load, we should provide useSWR()
with initialData
which still will require us to fetch data in getInitialProps()
, but it would be enough to just do this on the server side. Could use the new getServerSideProps()
. Current solution, using the solution described in bullet point number 2.
const HomePage = (props) => { return ( <Layout data={props.footer}> <Home data={props.page} /> </Layout> ) } // Not actual query, just sample const query = `{ "page": *[_type == "page"][0], "footer": *[_type == "footer"][0] }` HomePage.getInitialProps = async () => { const data = await client.fetch(query) return { page: data.page footer: data.footer } } export default HomePage
Would love some more insight into this. I'm a missing something obvious?
Disadvantages of NextJS Although NextJS is developing rapidly and many features arrive, it still has some cons and issues which you can see below: Cost of flexibility – Next JS does not provide many built-in front pages, so you have to create the whole front-end layer from the ground up.
js, the correct way to persist components between page changes is to use the custom App component. It's quite simple. All you have to do is to create the file /pages/_app. js if it doesn't exist already, and add the components you want to persist in there.
Data fetching in Next. js allows you to render your content in different ways, depending on your application's use case. These include pre-rendering with Server-side Rendering or Static Generation, and updating or creating content at runtime with Incremental Static Regeneration.
O'right! I found this thread while I was looking for something else. But since I had to work on similar issues, I can give you some directions, and I will do my best to make it clear for you.
So there are some data which you want to have it share, across your app (pages/components).
_app.js
file in root of pages
directory. For more information follow this link: https://nextjs.org/docs/advanced-features/custom-app getInitialProps
in your pages to fetch data from your API, you can also use the same method in _app.js
. So, I would fetch those data which I need to share them across my app and eliminate my API calls.Well, Now I can think of two ways to share the data across my app
createContext
hooks.1.1. Create a DataContext using createContext hooks. and wrap <Component {...pageProps} />
with your <DataContext.Provider>
. Here is a code snippet to give you a better clue:
<DataContext.Provider value={{ userData, footerData, etc... }}> <Component {...pageProps} /> </DataContext.Provider>
1.2. Now in other pages/components you can access to your DataContext like following:
const { footerData } = useContext(DataContext);
And then you are able to do the manipulation in your front-end
props
using getInitialProps
2.1. getInitialProps
is used to asynchronously fetch some data, which then populates props
. that would be the same case in _app.js
.
The code in your _app.js
would be something like this:
function MyApp({ Component, pageProps, footerData }) { //do other stuffs return ( <Component {...pageProps} footerData={footerData} /> ; } MyApp.getInitialProps = async ({ Component, ctx }) => { const footerRes = await fetch('http://API_URL'); const footerData = await footerRes.json(); let pageProps = {}; if (Component.getInitialProps) { pageProps = await Component.getInitialProps(ctx); } return { pageProps, footerData }; };
2.2. Now in your pages (not in your components) you can access to props including those you have shared from _app.js
and you can start to do you manipulation.
Hope I could give you a clue and direction. Have fun exploring.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With