Achinga
Achinga

Reputation: 55

Passing props to NextJS Layout Component

I have the layout component imported in the _app.js file:

Layout.js:

const Layout = ({ children, webName, pageTitle }) => {
  return (
    <div>
      <Head>
        <meta charSet='utf-8' />
        <meta
          name='viewport'
          content='width=device-width, initial-scale=1, shrink-to-fit=no'
        />
        <meta name='description' content='' />
        <meta name='author' content='Chris Achinga -> chrisdevcode.xyz' />
        <title>Feet Of Colors Foundation</title>
      </Head>
      <PageHeader webName={webName} pageTitle={pageTitle} />
      <NavBar webName={webName} />
      <main>{children}</main>
      <Footer />
    </div>
  )
}

export default Layout

The _app.js:

import Layout from '@/layout/Layout'
import '@/styles/globals.css'

export default function App({ Component, pageProps }) {
  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  )
}

I have different pages that I would love to pass different values to webName and pageTitle props, without using the Layout component in each file.

How do I achieve that?

Upvotes: 4

Views: 17626

Answers (2)

Predaytor
Predaytor

Reputation: 144

pages/_app.tsx:

import type { InferGetServerSidePropsType, NextPage } from 'next';
import type { AppProps } from 'next/app';

export type NextPageWithLayout<Props extends (args: any) => any> = NextPage<InferGetServerSidePropsType<Props>> & {
    getLayout?: (page: React.ReactElement, props: InferGetServerSidePropsType<Props>) => React.ReactNode;
};

export type AppPropsWithLayout = AppProps & {
    Component: NextPageWithLayout<any>;
};

export default function App({ Component, pageProps }: AppPropsWithLayout) {
    const getLayout = Component.getLayout ?? (page => page);

    return (
        <div className="root">
            {getLayout(<Component {...pageProps} />, pageProps)}
        </div>
    );
}

pages/index.tsx:

import type { GetServerSideProps } from 'next';
import type { NextPageWithLayout } from '~/pages/_app';

import { Layout } from '~/layouts/custom-layout';

export const getServerSideProps = (async () => {
    // ... query your data

    return {
        props: {
            data,
        },
    };
}) satisfies GetServerSideProps;

const IndexPage: NextPageWithLayout<typeof getServerSideProps> = props => {};

IndexPage.getLayout = (page, props) => <Layout>{page}</Layout>;

export default IndexPage;

Upvotes: 3

Ahmed Sbai
Ahmed Sbai

Reputation: 16239

you can make use of getServerSideProps to pass data to your Layout
The data returned by getServerSideProps is passed as props to the page. And this same props is accessible in _app.js, so you can pass it to the layout.

export default function MyApp({ Component, pageProps }) {
  return (
    // here you pass the pageProps to the layout
    <Layout pageProps={pageProps}>
      <Component {...pageProps} />
    </Layout>
  );
}

In your Layout component :

export default function Layout({ pageProps, children }) {
  console.log(pageProps); // see pageProps here
  return (
    <>
      <main>{children}</main>
    </>
  );
}

Finally in your Page :

export async function getServerSideProps() {
  return {
    props: {
      webName: "name",
      pageTitle: "title"
    },
  };
}

Upvotes: 4

Related Questions