score:-1

I was looking for same few weeks ago. If you have some component which wraps all the pages,or have a component which is displayed in all pages, then here is a video which describes the same.

Here is an example, from my own project.

_app.ts

import "../styles/global.css";
import "@fontsource/rubik";

import type { AppProps } from "next/app";
import { ThemeProvider } from "next-themes";

type ComponentWithPageLayout = AppProps & {
  Component: AppProps["Component"] & {
    PageLayout?: React.ComponentType<any>;
  };
};

const MyApp = ({ Component, pageProps }: ComponentWithPageLayout) => {
  return (
    <>
      <ThemeProvider attribute="class">
        {Component.PageLayout ? (
          <Component.PageLayout>
            <Component {...pageProps} />
          </Component.PageLayout>
        ) : (
          <Component {...pageProps} />
        )}
      </ThemeProvider>
    </>
  );
};

export default MyApp;

LayoutWithoutSidebar

import Navbar from "src/components/Navbar";

const LayoutWithoutSidebar = ({ children }: { children: React.ReactNode }) => {
  return (
    <>
      <header className="sticky top-0 z-50 ">
        <Navbar />
      </header>
      <main className="max-w-7xl m-auto">{children}</main>
    </>
  );
};

export default LayoutWithoutSidebar;

index.ts

import { GetStaticProps, GetStaticPropsContext, PreviewData } from "next/types";
import { ParsedUrlQuery } from "querystring";

import ApiService_ from "src/services/ApiService";

import PageHead from "src/components/PageHead";
import { Article, Project } from "src/@types/schema";

import LayoutWithoutSidebar from "src/layouts/LayoutWithoutSidebar";
import SectionSeperator from "src/components/SectionSeperator";

import IntroSection from "src/components/section/IntroSection";
import LatestSection from "src/components/section/LatestSection";


const Home = ({ latest, projects }: { latest: Article[]; projects: Project[] }) => {
  return (
    <div className="flex flex-col">
      <PageHead title="NextJS Blog" desc="Generated by create next app" />
      <IntroSection />
      <SectionSeperator />
      <LatestSection latest={latest} />
    </div>
  );
};

Home.PageLayout = LayoutWithoutSidebar; 

export default Home;

export const getStaticProps: GetStaticProps = async (
  context: GetStaticPropsContext<ParsedUrlQuery, PreviewData>
) => {
  const _service = new ApiService_();

  const latest: Article[] = await _service.getPost({
    maximum: 3,
    type: "Update",
  });

  const projects: Project[] = await _service.getProjects({});

  return {
    props: {
      latest,
      projects,
    },
  };
};

** Make a layout for example layout with Navbar,{children} (this is page content),Footer **

Home.PageLayout = LayoutWithoutSidebar; 

here is the video from where i learned. checkout for more learn detailed explanation How to Add Nested/Persistent Layouts in Next.js

score:36

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).

  1. Next.js uses the App component to initialize pages. You can override it and control the page initialization. to achieve that simply create _app.js file in root of pages directory. For more information follow this link: https://nextjs.org/docs/advanced-features/custom-app
  2. Just like the way you can use 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

  1. Using of 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

  1. populates 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.


Related Query

More Query from same tag