#Static content

25 messages Β· Page 1 of 1 (latest)

finite iron
#

I'm using NextJs 13 and I spent many hours trying to make my Strapi menu static once build.
I added a Layout to _app.js and a Menu.js component inside.
Unfortunately I recently found out that getStaticProps only works on pages and not in components.
Does anyone have a solution other than passing the menu data in each getStaticProps of each page?
I also will have a side bar on each page with data from Strapi
Thank you in advance

shell spruce
#

Are you using the app router or the traditional approach?

finite iron
#

I'm don't accepted experimental app folder.
And for the route I think using the traditional way.
I have my index.js, [page].js & [post].js

#

I created a wrapper for getStaticProps but I have to use it on all pages.

export function withMenu(getStaticPropsFunc) {
  return async function (context) {
    const menuPromise = getMenuData();
    const pagePropsPromise = getStaticPropsFunc ? getStaticPropsFunc(context) : { props: {} };

    const [menuItems, pageProps] = await Promise.all([menuPromise, pagePropsPromise]);

    return {
      props: {
        menuItems,
        ...pageProps.props,
      },
      revalidate: Math.max(pageProps.revalidate || 0, 60),
    };
  };
}```
shell spruce
#

Your <Menu /> component needs to be in your <App /> component and accept the menu content via props. These menu props need to be returned from getInitialProps.

finite iron
#

Thank you Tobias I will try this right now

shell spruce
#

Feel free to let me know how it goes πŸ™‚

finite iron
#

_app should look like this right ?

function App({ Component, pageProps, menuItems}) {

  useEffect(() => {
    require("bootstrap/dist/js/bootstrap.bundle.min.js");
  }, []);

  return (
    <Layout menuItems={menuItems}>
      <Component {...pageProps} />
    </Layout>
  )
}

App.getInitialProps = async () => {
  const menuItems = await getMenuData();
  return { menuItems}
}

export default App
shell spruce
#

I think menuItems will be contained in pageProps

finite iron
#

It's working

#

Thank you very much. I spend half a day to find the wrapper way...

#

It's better like that πŸ˜„

#

Can I ask you one more thing @shell spruce ?

shell spruce
#

Sure!

finite iron
#

I'm new on nextjs and sometime when there is an issue like miss import or variable that don't exist or wrong json return, I feel that it's hard to debug, the messages are not accurate most of the time. Should I setup something to debug ? Actually i'm only using npm run dev.

shell spruce
#

What editor are you using?

finite iron
#

vscode

shell spruce
#

Also, would you be interested in learning another way to solve your problem?

finite iron
shell spruce
#

So getInitialProps disables automatic static optimization in Next. Pages with that function can't be static, they will always be rendered for each request. Since we added this function to _app.js, this has huge implications because I'd expect your app can't be static this way. (https://nextjs.org/docs/advanced-features/automatic-static-optimization)

You could try to get around this with next export, but this removes a large chunk of cool Next features, so you also probably don't want that πŸ˜„ (https://nextjs.org/docs/advanced-features/static-html-export)

Your initial approach is actually good because it adds the getMenuData query in a clean way. Problem is that this didn't work because Next needs the getStaticProps function, I don't think you can wrap it. But what you still could do is create a utility function you call inside getStaticProps to get the menu data. To streamline this even further, you could create a <Page /> component that renders the menu and the page content. So your [post].js would basically become something like this:

export function Post(props) {
  return <Page {...props} />
}

export const getStaticProps = async ({ params }) {
  // Fetch menu data
  const menuItems = await getMenuData();

  // Fetch your page content
  const pageContent = getPageContent();

  return {
    props: {
      menuItems,
      pageContent
    }
  }
}

And <Page /> would be something like this:

export default function Page({menuItems, pageContent}) {
  return <>
    <Menu items={menuItems} />
    <main>{pageContent}</main> // Probably too simple :D
  </>;
}
#

I hope this isn't too hard to follow πŸ˜… This way you could have a menu and your app still could be static. If this works for you depends on your use case though.

finite iron
#

Thank you so much for all the explanation ! Indeed I will need to keep my pages statics for performance !
And make a wrapper worked for me !
You can try on you side for future use case πŸ™‚


    const urlParamsObject = {
        filters: {
            slug: "home",
        },
        populate: "deep",
    }
    const queryString = qs.stringify(urlParamsObject);
    const { data } = await api.get(`/pages${queryString ? `?${queryString}` : ""}`);
    const pageData = data.data[0];

    return { props: { data: pageData } };
}

export default HomePage;
export const getStaticProps = withMenu(getStaticPropsIndex);```
shell spruce
#

Awesome stuff, I'm glad this works for you!