2

I am using nextjs version 12.1.6, react-dom version 18.0.5, next-auth 4.6.1, I have an application with 2 routes at the moment, an index page and a login page, when I route from the index page to the login page and vice versa, my whole app rerenders, I have react-profiler and the given reason is context change, I assume its have to do something with the SessionProvider from next-auth but why it rerenders my whole app?

enter image description here

as you can see I have a HeaderComponent that did NOT rerendered, this is because I used React.memo on it, but I dont want to wrap all my components in React.memo, also this component is used inside on a Layout component pages/_app.tsx

my _app.tsx

function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <Head>
          <title>foo</title>
          <meta name="description" content="Generated by create next app" />
          <link rel="icon" href="/favicon.ico" />
      </Head>
  
      <SessionProvider session={ pageProps.session }>
        <LayoutComponent>
          <Component {...pageProps} />
        </LayoutComponent>  
      </SessionProvider>  
    </>    
  );
}

also I am using nextjs Link jsx element for routing

my LayoutComponent:

const LayoutComponent = ({ children }: PropsWithChildren) => {
    return (
        <>
            <HeaderComponent 
                homePath='/'
                signinPath='/auth/signin'
                aboutPath='/about'
            />
                <main>
                    { children }
                </main>
            <FooterComponent />
        </>
    );
}

export default LayoutComponent;
dsal3389
  • 658
  • 1
  • 7
  • 26

1 Answers1

1

Okay, I'll give it a shot.

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

export default MyApp

Component in the code above is your page (Login/Index). Whenever you navigate to a page from another one by clicking a Next Js link, your Login/Index component will be fetched from the server and then React will compare the new and old component and re-render since they are different.

function MyApp({ Component, pageProps }) {
  return (
    <VerticalLayout>
      <Component {...pageProps} />
    </VerticalLayout>
  )
}

export default MyApp

If you put your page component between opening an closing tags of a layout component like above, only the corresponding component will be re-render again but VerticalLayout will stay untouched.

const VerticalLayout = ({children}) => {
  return (
    <div id="layout-wrapper">
      <HeaderComponent />
      <main>
        <Sidebar />
        <div className="main-content">{children}</div>
      </main>
      <FooterComponent />
    </div>
  )
})

You can then place your header/footer components in that component like above. So that they will not be re-render when you navigate to a different page.

Ahmet Firat Keler
  • 2,603
  • 2
  • 11
  • 22
  • Hi, nope, didn't work, I edited my question, and added my `pages/_app.tsx` content – dsal3389 Jun 26 '22 at 13:46
  • Your code looks different than mine. I shared an example with one wrapping component in which I put the rest such as header and footer. – Ahmet Firat Keler Jun 27 '22 at 06:04
  • yeah but I am using `next-auth` so I need that SessionProvider wrapper – dsal3389 Jun 27 '22 at 12:15
  • @AhmetFiratKeler's answer worked for me. Here's a shortened version of his answer: - `` renders whatever is on the active page. [Learn more](https://nextjs.org/docs/advanced-features/custom-app). - Use `` only in the `MyApp` component to wrap ``. Rather than using it on every page to wrap the pages' elements. - Move whatever you wish to persist between route changes into ``. By so doing, when you route to a new page, ``'s content will remain intact. While `` will display the new page's items. – OluwatobiSS Apr 13 '23 at 13:42