Skip to content
Advertisement

Best practice for Next.js data fetching inside a component

I have a menu component that appears globally. What is the best practice for getting data into that component?

I’m trying to take advantage of static generation that Next.js offers but all data fetching guidance from the Next.js team relates to pages. getStaticProps and getStaticPaths seem to pertain to page generation, not data for components. Is their SWR package the right answer, or Apollo Client?

Typically in hooks-based React, I’d just put my data call into useEffect. I’m not sure how to reason this out being that everything is rendered at build time with Next.

Advertisement

Answer

This is such a tricky problem, I think we need to lay out some background before a solution comes into focus. I’m focusing in the React.js world but a lot of this would apply to Vue/Nuxt I’d imagine.

Background / Static Generation Benefits:

Gatsby and Next are focused on generating static pages, which vastly improves performance and SEO in React.js sites. There is a lot of technical overhead to both platforms beyond this simple insight but let’s start with this idea of a digital machine pumping out fancy HTML pages for the browser.

Data Fetching for Pages

In the case of Next.js (as of v9.5), their data fetching mechanism getStaticProps does most of the heavy lifting for you but it’s sandboxed to the /pages/ directory. The idea is that it does the data fetching for you and tells the Next.js page generator in Node about it during build time (instead of doing it component-side in a useEffect hook – or componentDidMount). Gatsby does much the same with their gatsby-node.js file, which orchestrates the data fetching for page building in concert with a Node server.

What about Global Components that need data?

You can use both Gatsby and Next to produce any kind of website but a huge use case are CMS-driven websites, because so much of that content is static. These tools are an ideal fit to that use case.

In typical CMS sites, you will have elements that are global – header, footer, search, menu, etc. This is where static generation faces a big challenge: how do I get data into dynamic global components at build time? The answer to this question is… you don’t. And if you think about this for a minute it makes sense. If you had a 10K page site, would you want to trigger a site-wide rebuild if someone adds a new nav item to a menu?

Data Fetching for Global Components

So how do we get around this? The best answer I have is apollo-client and to do the fetch client side. This helps us for a number of reasons:

  • For small size queries, the performance impact is negligible.
  • If we need to rebuild pages for changes at the CMS layer, this slides by Next/Gatsby’s detection mechanisms, so we can make global changes without triggering gigantic site-wide rebuilds.

So what does this actually look like? At the component level, it looks just like a regular Apollo-enhanced component would. I usually use styled-components but I tried to strip that out so you can could better see what’s going on.

JavaScript

Set Up for Next to Use Apollo

This is actually really well documented by the Next.js team, which makes me feel like I’m not totally hacking the way this tool is supposed to work. You can find great examples of using Apollo in their repo.

Steps to get Apollo into a Next app:

  1. Make a custom useApollo hook that sets up the connection to your data source (I put mine in /lib/apollo/apolloClient.js within Next’s hierarchy but I’m sure it could go elsewhere).
JavaScript
  1. Modify _app.js in the /pages/ directory of Next. This is basically the wrapper that goes around every page in Next. We’re going to add the Apollo provider to this, and now we can globally access Apollo from any component.
JavaScript

And now you can get dynamic data inside of your components using Apollo! So easy right 😉 HA!

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement