10
votes

I would like to be able to retrieve data from an API, server-side, and load it into React context, in order to make it available to any component in my app. I have tried various things, but nothing seems to allow me to do exactly what I want. Some things I've tried include:

getServerSideProps - This allows me to retrieve the data, server-side, but only exists for Page components, so if I want this available on every page, and I don't know which page my user will land on, I'll need to add logic for this to every single page.

getInitialProps in _app.js - I can add this to the _app.js component, which will run server-side, and can make it available to all components via a context provider, but the problem is that it runs on every single page, even when navigating client-side. I would like to be able to call the API once and only once, and this doesn't seem to allow that.

getInitialProps in _document.js - I can add this to the _document.js component, which only runs on the server, which seems to address the problem of it being called for every page, but I cannot figure out how to store it in React context from there. In fact, I can't seem to figure out how to access this data anywhere. It looks like getInitialProps in _document.js is called after getInitialProps in _app.js, so I'm not sure if I can use the value I generate from getInitialProps in _document.js when I am in _app.js.

There are a number of ways I can make this work if I call the API on the client, but that won't work for my use case as it will cause a flash of content when the client updates with the data from the API.

Has anyone come up with a way of addressing this use case?

3

3 Answers

7
votes

In Next.js, there's no native function to a) retrieve data from an API, b) do it on the server, c) make it available on every page, and d) only query the API on the first page the user visits.

As you've found out, getInitialProps and getServerSideProps will run every time you visit that page.

However, we can get this to work.

If you need the data before the initial load

  1. Use getInitialProps in _app.js to retrieve data from the API
  2. Load the data into React context inside the _app.js file so it persists between pages
  3. When the browser gets the data, create a cookie.
  4. On a subsequent page load, in getInitialProps, check if there's a cookie. If so, don't retrieve the data.

There's a fairly popular library called nookies to help with cookies in a Next.js project.

If you can load the page then fetch the data

There is a performance cost to using getInitialProps in _app.js: you'll never be able to create a fully static page. That's because getInitialProps will have to run on every single page load.

If you can fetch the data after page load, add an API route. Then, in the context provider, use useEffect to fetch the data.

0
votes

You can try using getInitialProps in the Page Component itself

This way, the data fetching will only happen for that exact page.

0
votes

Maybe Redux could be a solution for your issues. Context api tends to trigger unnecessary re rendering of the consumers.