Navbars, Footers, and Menus

Package versions

These docs use the following package versions:

  • prismic-reactjs: v1.3
  • @prismicio/client: v5

The docs will soon be updated to use the latest versions of these packages. If you wish to use the latest versions today, you can update your project by following the migration guides for each package.

As discussed in the Query content from the CMS article, to query content outside the SliceZone of your document, you need to perform another query. For menus or footers, it's a little different as you'll not want to query the menu on every page; we'll show you the best practice for doing this below.


Model the menu in Prismic

In this example, we have created a Single type Custom Type for the menu as we won't be creating many versions of the document. We have a Title field and a Group field inside the menu type.

In the Group field, we added a Link field and a Rich Text field, this way you can add as many links as you need. From here you can create a new menu document in your dashboard and add your content.

Copy
{
  "Main" : {
    "title" : {
      "type" : "StructuredText",
      "config" : {
        "placeholder" : "Menu title...",
        "single" : "heading1"
      }
    },
    "menu_links" : {
      "type" : "Group",
      "config" : {
        "fields" : {
          "label" : {
            "type" : "StructuredText",
            "config" : {
              "single" : "paragraph",
              "label" : "Link Label",
              "placeholder" : "Link Label..."
            }
          },
          "link" : {
            "type" : "Link",
            "config" : {
              "label" : "Link",
              "placeholder" : "Select a Link..."
            }
          }
        },
        "label" : "Menu Links"
      }
    }
  }
}

Query the menu

Open the _app.js file. Then query for the single instance of the Custom Type "menu" using the query helper function getSingle from the Javascript development kit. This query will be located inside the getInitialProps fetching method.

Then, pass the menu as props to the <Component /> in the render method.

Copy
import React from 'react'
import Prismic from '@prismicio/client'
import NextApp from 'next/app'

// Update your-repo-name with the name of your repository.
const apiEndpoint = 'https://your-repo-name.cdn.prismic.io/api/v2'
const Client = Prismic.client(apiEndpoint, { req })

export default class MyApp extends NextApp {
  static async getInitialProps(appCtx) {
    const menu = (await Client().getSingle("menu")) || {};
    return {
      props: {
        menu: menu
      },
    };
  }

  render() {
    const { Component, pageProps, props } = this.props
    return (
      <Component {...pageProps} menu={props.menu} />
    )
  }
}

Create the components

Create a /components folder in your Next.js project and add these files inside of it:

  • Layout.js
  • Header.js

Create a Layout

In the Layout.js file, retrieve the menu from the props in this file and pass it to the Header.js component. Make sure that all the imports match your project routes.

Copy
import React from 'react'
import Head from 'next/head'

// Update the path for your Header component.
import Header from '../path-to-your-header-component'

const Layout = ({ children, menu, isPreview }) => {
  const menuLinks = menu.data.menu_links;
  return (
    <div>
      <Head>
        <title> Prismic Next.js Multi Page Website</title>
      </Head>
      <Header menuLinks={menuLinks} />
      <main>{children}</main>
    </div>
  );
};

export default Layout;

Create a header

In your Header.js file, access the menuLinks props from Layout.js and use them to create the menu,

Copy
import React from "react";
import { RichText, Link } from "prismic-reactjs";

const Header = ({ menu = [] }) => (
  <header>
    <a href="/">{RichText.asText(menu.data.title)}</a>
    <Links menuLinks={menu.data.menu_links} />
  </header>
);

const Links = ({ menuLinks }) => {
  if (menuLinks) {
    return (
      <nav>
        <ul>
          {menuLinks.map((menuLink, index) => (
            <li key={`menulink-${index}`}>
              <a href={Link.url(menuLink.link)}>
                {RichText.asText(menuLink.label)}
              </a>
            </li>
          ))}
        </ul>
      </nav>
    );
  }
  return null;
};

export default Header;

Add the layout to your pages and pass it props

Now, wrap all your pages with the Layout component and pass the menu as props. Here we give you an example of the index.js file for a homepage, but you can add it to every other page you create. In the example, we reference the Client, learn how to set that up here.

Copy
// Example 〜/pages/index.js file

import { Client } from "../utils/prismicHelpers"; 
import SliceZone from "next-slicezone";

import Layout from "./../components/Layout"; // path-to-your-layout-component
import * as Slices from "../slices";
const resolver = ({ sliceName }) => Slices[sliceName];

const Home = (props) => {
  return (
    <Layout menu={props.menu}>
      <SliceZone slices={props.slices} resolver={resolver} />
    </Layout>
  );
};

export async function getStaticProps() {

  const doc = await Client().getSingle("home-page") || null

  return {
    props: {
      slices: doc.data.slices
    }
  }
}

export default Home;

That's it, now you have a Layout with a menu that you can modify to your liking.


Related articles


Was this article helpful?
Not really
Yes, Thanks

Can't find what you're looking for? Get in touch with us on our Community Forum.