Insights

Dynamically Generating Pages in NextJS using WordPress

Previous to NextJS 9, implementing dynamic routes for your NextJS setup was a bit of a pain. It required you to understand how to create logic which would involve passing in query parameters to a custom back-end, fetching the data required to render the route and then passing it back to NextJS to create the page.

With the introduction of NextJS 9, you can now dynamically create routes for your site in under 10 minutes with a little configuration.

This is a guide on how to do just that with a real-world example using my WordPress setup. The WordPress setup uses custom endpoints but these will work with the default REST endpoints introduced in WordPress 4.7.0.

All of the code used in this example is open source and available to download - https://github.com/whatjackhasmade/Dynamically-Generating-Pages-in-NextJS

Final Result

The final result will look something like this -



The example is a NextJS setup which is pulling in JSON from a WordPress domain. When we swap out the slug in the NextJS setup, the page will dynamically change where it looks for the JSON on the WordPress site.

As I currently only have two pages on the WordPress domain, there are only 2 valid slugs that work, ‘about’ and ‘homepage’. You can see what these pages look like in NextJS by visiting either URL -

  1. https://dynamically-generating-pages-in-nextjs.jackp.now.sh/about
  2. https://dynamically-generating-pages-in-nextjs.jackp.now.sh/homepage

Following Along

If you’d like to follow along, you can do so by cloning my repository from GitHub. Run git clone https://github.com/whatjackhasmade/Dynamically-Generating-Pages-in-NextJS.git from your terminal.

Once cloned, open up a terminal window in the folder, run npm install or yarn install to get our required packages.

Then run the start command with npm run start or yarn run start.

This will start a NextJS server at http://localhost:3000/

If you go there, you’ll find a 404 page, but if you go to http://localhost:3000/about you’ll see some JSON data which we’ll be covering in detail next.

Dynamic Routing

“Next.js supports creating routes with basic named parameters, a pattern popularized by path-to-regexp (the library that powers Express).”

NextJS 2019

To create these routes, you will need to add a new file in your ‘pages’ directory. The name of the file can be whatever you want, but the name you choose will be the name of the prop available later on in your code.

In this example, we are going to create a page route, so the syntax will be [page].js, and the prop available will be named page. If you wanted the prop to be slug, you’d name the file [slug].js

The directory path used for this file will also hold influence in the URL used to access the new route. So if you wanted a blog post to be domain.com/blog/slug-of-post then you’d create a folder in pages called blog and then the route file ([page.js]) within that folder.

With this new file, NextJS will handle all the magic of automatic dynamic page route handling and call upon our page template file. Speaking of which, It’s now time for us to create the page template file which will use the data passed in by NextJS.

Creating Our Page Template File

For those unfamiliar with NextJS, there is a special function which is available to all NextJS pages called getInitialProps. This is a function which gets called before the render of any page and passes data to the rendered component to use in any way you want.

In our page template, we will use the getInitialProps function asynchronously to fetch data from my WordPress API dynamically.

Package and Component Imports

Before we get started we first need to import React to build our application; and ‘fetch’ from isomorphic-fetch to increase browser support for our application (old browsers don’t support fetch).

import react from "react";
import fetch from "isomorphic-fetch";
import Debugger from "../components/Debugger";

const page = props => {
    return (
        <>
            <Debugger data={props.content} />
        </>
    );
};

Next, we are importing a custom component I use in all of my React applications called ‘Debugger’. It’s helpful for outputting JSON data in a styled format which I prefer to use to debug data without the need of accessing the console.

Creating the Page Component

To create the page template component itself, this is a functional component which returns the page which includes the debugger component in an unnamed React Fragment (<></>). The fragment isn't essential but if I were to nest any children on the page with Debugger then it'd be required.

The debugger component is using the content prop to feed data for rendering in our application. That way we can see what data our endpoint is giving us. The data value is set in the next part of this article.

Fetching Data Dynamically from our WordPress Endpoint

Now comes the focus of the article, the dynamic fetching of data in the getInitialProps function.

page.getInitialProps = async ({ query }) => {
    const res = await fetch(`https://wjhm.noface.app/wp-json/pages/v2/all?slug=${query.page}`);
    let data = await res.json();
    data = data[0];
    return data;
};

We are first destructuring our props object and get the value of the query key. This query object contains the slug of the page that was used in the URL that the user is accessing in our application. E.g. domain.com/page/title-goes-here would produce a query object with a page key, the page key would have the value title-goes-here.

Next, we create a GET request using the fetch function that we’ve imported. The URL value is a string that when created using backticks (`) gives us the option to inject values from objects, variables, const, let, etc. within the string using ${value}.

As query.page contains the slug of the page we want data from, we will pass this into the fetch request. My WordPress API has been set up to accept a page slug as a query parameter and will return page information based on the parameter value. If no value is provided, it will return information on all of the pages available.

The only constant in our fetch request is the domain and path used to get to the page API in WordPress.

After fetching our data, we then assign it to a variable named ‘data’.

We only want to get access to the content key in the endpoint, this has access to our page blocks from Gutenberg, and as the data from the endpoint contains a number of different fields of information that we are interested in; we will narrow our data’s focus by assigning the data variable to the data available in the first entry in our API’s array by using data = data[0].

Finally, we return this data in the getInitialProps function, exposing it to our page template component.

Viewing our Dynamic Routes/Pages

With our page template written, we can now start our NextJS server up by running our start script from our package.json file. Our start command will run ‘next start’ which starts our next server.

Locally we can access this server at http://localhost:3000 and access our endpoint at http://localhost:3000/about which will render the data found at our WordPress endpoint on the about page. When we add pages to WordPress in the future, they will automatically get picked up by our dynamic routing in our NextJS application.

Final Code Snippet

import react from "react";
import fetch from "isomorphic-fetch";
import Debugger from "../components/Debugger";

const page = props => {
    return (
        <>
            <Debugger data={props.content} />
        </>
    );
};

page.getInitialProps = async ({ query }) => {
    const res = await fetch(`https://wjhm.noface.app/wp-json/pages/v2/all?slug=${query.page}`);
    let data = await res.json();
    data = data[0];
    return data;
};

export default page;

Future Improvements

As you can see dynamic routing has huge benefits, if a content manager of a site wants to create a new blog post or page, they can do so without asking the developer of the site to add a file to the front-end or implement dynamic route logic in the backend.

The only caveat with the current setup is that the homepage should render at the index route of the site (sitedomain.com) with or without a forward slash.

You can get around this by creating an index.js file in your pages directory and setting up the same logic as our [page].js file but instead of dynamically populating the slug in the API, you can set a fixed slug of ‘homepage’.

You could also set up a redirect on your site for if anyone hits /homepage to be redirected to the index of the site.

Further Learning

If you want to learn more about Next, Gatsby and React, follow me on Twitter (@whatjackhasmade) where I share the latest information and news as it comes out. I’d also love to chat about your ideas and implementations of the NextJS dynamic routing and any suggestions you have!

Useful Links -

Continue Reading 📚

Tell Me About Your Project