How to fetch data for a reusable layout component in Next.js

Viewed 3624

I need to put slugs in my Header component which is reusable in all the site inside the layout:

const Layout = ({ children }) => {
  return (
    <>
      <Header />//////////this one.
      {children}
      <Footer />
     </>
  );
};

My slugs goings from the server side and I need to dynamically fetch them only one time in the header.

Inside the header something like:

categoriesLinks.map(category=> {
  return <div>{category.SLUG}</div>
})

But because it's a reusable component I don't know how and where to invoke the getServerSideProps or getStaticProps.

  • if I use the index component for example I need to fetch data in every component
  • if I tried to fetch it inside getInitialProps in the _app, it doesn't get it (get undefined)

What is the right way to handle this? It seems like a really big issue and I couldn't find the right solution for this.

2 Answers

You can't call getServerSideProps or getStaticProps in a component. You have to write the getServersideprops or getStaticProps inside the page and then pass the fetched data to the layout. You can also use a state management system like react context or recoil (recommended) to save the data so you won't have to re-fetch every time and then in the layout do the following

useEffect(() => ChangeData(data), [])

This code will render your data once. ChangeData is the stateChanger for recoil or react context.

This is what I found on Vercel https://nextjs.org/blog/layouts-rfc#data-fetching-in-layouts via an ongoing discussion on https://github.com/vercel/next.js/discussions/10949


You can fetch data in a layout.js file by using the Next.js data fetching methods getStaticProps or getServerSideProps.

For example, a blog layout could use getStaticProps to fetch categories from a CMS, which can be used to populate a sidebar component:

// app/blog/layout.js

export async function getStaticProps() {
  const categories = await getCategoriesFromCMS();

  return {
    props: { categories },
  };
}

export default function BlogLayout({ categories, children }) {
  return (
    <>
      <BlogSidebar categories={categories} />
      {children}
    </>
  );
}

To see

Related