Navigation bar re-rendering on route change

Hello, I am using NextJS with builder, and I am trying to stop the navigation bar from re-rendering whenever the page route changes I created a data model called navigation-bar. I have also tried doing this with a section model using BuilderComponent in place of my NavigationBar component in _app.tsx. Not sure what I’m missing.

NavigationBar.tsx

export const NavigationBar = (props: any) => {
   return (
      <BuilderContent model="navigation-bar">
         {(data) => {
            return (
               <>
                  <ul>
                     {data?.navigationLinks?.map((link: any) => {
                        return (
                           <a key={link.linkUrl} href={link.linkUrl}>
                              {link.linkText}
                           </a>
                        );
                     })}
                  </ul>
                  {props.children}
               </>
            );
         }}
      </BuilderContent>
   );
};

_app.tsx

function MyApp(props: any) {
   let { Component, pageProps } = props;
   console.log("props", props);
   return (
      <>
         <NavigationBar />
         <Component {...pageProps} />;
      </>
   );
}

export default MyApp;

[[…pages]].tsx

export async function getStaticProps({
   params,
}: GetStaticPropsContext<{ page: string[] }>) {
   const page =
      (await builder
         .get("page", {
            userAttributes: {
               urlPath: "/" + (params?.page?.join("/") || ""),
            },
         })
         .toPromise()) || null;

   return {
      props: {
         page,
      },
      revalidate: 5,
   };
}

export async function getStaticPaths() {
   const pages = await builder.getAll("page", {
      options: { noTargeting: true },
   });

   return {
      paths: pages.map((page) => `${page.data?.url}`),
      fallback: true,
   };
}

export default function Page({
   page,
}: InferGetStaticPropsType<typeof getStaticProps>) {
   const router = useRouter();
   if (router.isFallback) {
      return <h1>Loading...</h1>;
   }
   const isLive = !Builder.isEditing && !Builder.isPreviewing;
   if (!page && isLive) {
      return (
         <>
            <Head>
               <meta name="robots" content="noindex" />
               <meta name="title"></meta>
            </Head>
            <DefaultErrorPage statusCode={404} />
         </>
      );
   }

   return (
      <>
         <Head>
            <meta
               name="viewport"
               content="width=device-width, initial-scale=1"
            />
         </Head>
         <BuilderComponent model="page" content={page} />
      </>
   );
}

I solved this. It has nothing to do with builder.io but more with state management of nextjs.
I had to create a state variable in my _app.tsx file to store the result of this call:

const content = await builder
      .get("navigation-bar", { url: context.resolvedUrl })
      .promise();

   return {
      props: { content },
      revalidate: true,
      notFound: !content,
   };

then I check if the app already has the content with a small function.

  const getContent = () => {
      if (content) return content;
      setContent(pageProps.content);
   };
   return (
      <>
         <BuilderComponent content={getContent()} model="navigation-bar" />
         <Component {...pageProps} />
      </>
   );

full _app.tsx code

function MyApp(props: any) {
   let { Component, pageProps } = props;
   const [content, setContent] = useState(undefined);

   const getContent = () => {
      if (content) return content;
      setContent(pageProps.content);
   };
   return (
      <>
         <BuilderComponent content={getContent()} model="navigation-bar" />
         <Component {...pageProps} />
      </>
   );
}
1 Like

Great, looks good @mflores thank you for the update!!