
Hi, I am Haris and will teach you how to create, manage and optimize a React SPA using a Headless WordPress backend through two blogs. In this first blog, I will explain the following: how we work with dynamic routing, create meta tags in a React SPA, how to install WordPress trough Docker, make use of ACF and how to use the Google Search Console. SSR is not needed in order to create a simple but manageable promotion website or blog. I will explain how we set up our basic WordPress environment on our local machine using Docker and making use of the integrated Rest API from WordPress. Next, we will learn how to make use of React Router and how to implement dynamic routing in our React environment. In part 2 I will discuss how we can expose our environment online for SEO.
Why WordPress?
WordPress is super simple to use, it’s very user-friendly, easy to update and has already done a lot of the work for us. To create a CMS from scratch can be very challenging and time-consuming. Since the 4.7 update in WordPress, we can make use of the WordPress REST API without making any modifications. The REST API will serve as our backend and will hold and manage the content for our website. In addition, tools like ACF (Advanced Custom Fields) can aid us in customizing our posts and pages. This way we can create a completely custom website trough a familiar platform like WordPress. Tools like Yoast SEO can help us with Search Engine Optimization and managing our indexation for Google’s Search Bot.
Why React SPA?
For the past 2.5 years, I have worked with React and seen many implementations done via this amazing library. React allows the developer to create complete unique UI’s that can enhance the UX of a website tremendously. SPA and SEO usually don’t go together quite well, mainly because of Google’s Search Engine not being able to render trough most of the Javascript. There are a couple of solutions/tricks that can aid us in achieving a well-optimized SPA.
What is an SPA?
SPA stands for Single Page Application. Unlike other websites and frameworks that have multiple pages, React allows us to never leave a single page. That’s right! You can create a complete website with just one page. React works by manipulating a single division on one page, called the “root
Note:
This guide will show examples using OSX, some terminal commands may be different between operating systems. If you have any questions on how to execute commands on your OS feel free to contact me.
Installation/Setup
In order to create a WordPress and React environment we have to install a couple of things. In this tutorial we will create an environment that is local for us. If you would like to host your set-up and learn more about DevOps check out this blog.
WordPress + Docker
Usually, WordPress requires an apache set up that will run the PHP for the WordPress environment. As a developer. we don’t want to manually configure everything. A great solution is to use Docker. We can run a local instance of a Docker container that will create our WordPress environment using compose. The WordPress installation can be different for Mac, Windows and Linux. You can find the docker installation guide here.
Once you have installed Docker on your local machine we can create our new WordPress site. There should be a basic understanding of how a terminal works in the next parts.
Let’s start by creating an empty folder where we will store the docker-compose.yml file.
mkdir wordpress-backend to create the WordPress-backend folder.
Navigate to the folder and create our docker-compose.yml file.
touch docker-compose.yml
Next up we add the following code to it
- version: '3.3'
- services:
- db:
- image: mysql:5.7
- volumes:
- - db_data:/var/lib/mysql
- restart: always
- environment:
- MYSQL_ROOT_PASSWORD: somewordpress
- MYSQL_DATABASE: wordpress
- MYSQL_USER: wordpress
- MYSQL_PASSWORD: wordpress
- wordpress:
- depends_on:
- - db
- image: wordpress:latest
- ports:
- - "8000:80"
- restart: always
- environment:
- WORDPRESS_DB_HOST: db:3306
- WORDPRESS_DB_USER: wordpress
- WORDPRESS_DB_PASSWORD: wordpress
- WORDPRESS_DB_NAME: wordpress
- volumes:
- db_data: {}
These are the default settings for creating a WordPress environment. Now if you run docker-compose up docker will run in detached mode, pull the required Docker images and start the WordPress and database containers. You should see something like this:
| Creating network "wordpress-backend_default" with the default driver | |
| Creating wordpress-backend_db_1 ... done | |
| Creating wordpress-backend_wordpress_1 ... done |
Docker compose will host a local host environment that you can visit. Here you will be able to run the installation of WordPress (filling out the database might be different per install, you can leave it as default for now). You can set up the installation settings in any way you want, as this is not significant at this stage. Just make sure to uncheck the search engine visibility.
Now login to your website using the username and password you set. We don’t have to install anything else to access our Rest API since WordPress 4.7. In order to test if the API of our WordPress works for you, you can fire a get request in Postman or just visit the link. We can also check our Hello World post. You should be able to see the example page created by WordPress. Let’s create a couple of pages to simulate a real website.
You can now check all the pages available in the REST API.
Note:
you can always change the URL of your REST API using permalinks. In order to do so go to Settings > Permalinks . This will also change the URL of the REST API.
React + React Router
So now that we have our WordPress environment set up we can start working on the React part. React works with a Virtual DOM by manipulating the root div on our web page and allows a single page while the application changes or interacts with the user. That’s why React is a SPA. But we don’t want to be on one page, we would like to have multiple pages and navigate by changing the URL. This is where React Router will come in. React Router will serve as a navigation tool through our React SPA. It will simulate Routes by adjusting the URL and change the content on the page. Let’s start by creating a basic React App. For this, we will use NPM and Node. SO, create a new folder, outside the WordPress folder. Here we will create our app.
npx create-react-app wordpress-frontend
Then navigate to the folder and run it
cd wordpress-frontend && npm start
You should see the base create-react-app landing page.
Next, we will need some data before we actually start creating routes. Our routes will be based on the pages that exist in our WordPress environment. The first step will be to connect our frontend and backend to receive the content for us to display. In order to receive the pages, we have to GET the content from WordPress. We use the library Axios for this. Axios is basically the same as Fetch but has a couple of important added features. Some benefits of Axios:
- Transformers: allow performing transforms on data before a request is made or after a response is received (We can use this later to only fetch differences to increase the performance
- Interceptors: allow you to alter the request or response entirely (headers as well). Also, perform async operations before a request is made or before Promise settles. (This will be handy for spoofing 404 responses so pages that do not exist do not get indexed.)
- Built-in XSRF Protection
Our content comes from the headless WordPress and will determine what pages/links/posts will be available. Luckily Axios allows us to work with promises what will come to a great benefit to us. First, we add Axios to our project with:
npm install axios
Then, let’s modify our App.js file in the src folder to reach out for the pages and display the page-slugs on our website.
- import React, { Fragment } from "react";
- import axios from "axios";
- import "./App.css";
- export default class App extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- pages: []
- };
- }
- getAllPages = async () => {
- let res = await axios.get(
- `http://localhost:8000/?rest_route=/wp/v2/pages`
- );
- let { data } = await res;
- this.setState({ pages: data });
- };
- componentDidMount = async () => {
- await this.getAllPages();
- };
- render() {
- const { pages } = this.state;
- return (
-
- {pages.map((page, index) => {
- return
{page.slug}
; - })}
- );
- }
- }
The reason we use a class is to be able to use the constructor and add a pages state. We can then use the array that will be stored in this.state.pages to render our pages dynamically. The reason we use a pages state to store pages is so that we are able to store pages in the cookies or local storage of the user. Before we actually fetch the content we can then compare the local storage and our WordPress environment. We will discuss further optimization in the second blog.
“You can also use React Hooks or State if you want to. You can read more about it here: https://reactjs.org/docs/hooks-state”
Haris Spahija
Secondly, we will perform the function componentDidMount to get all of our pages. getAllPages will fetch the pages from our WordPress and store them into the state. In the render, we will perform a map of our state to render the slugs of our pages. You should see something like this.
Great! Now we can see that we get some data loaded into our website. Next, we will create individual pages, so we can visit them.
Let’s install react-router to create routing for React. npm install react-router-dom
React Router allows us to create individual routes for our pages and adjust our URL. In order to dynamically create the routing, we can add the following code. Don’t forget to import react-router-dom
Let’s change the following code inside the render function to:
- // Import Router at the top of the page
- import {
- BrowserRouter as Router,
- Link,
- Route
- } from "react-router-dom";
- render() {
- const { pages } = this.state;
- return (
-
-
- {/* Links */}
-
- {pages.map((page, index) => {
- return {page.slug};
- })}
- {/* Routing */}
- {pages.map((page, index) => {
- return (
-
- exact
- key={index}
- path={`/${page.slug}`}
- render={props => (
- )}
- />
- );
- })}
- );
- }
Create a folder inside the
src folder called components and add ExamplePage.js to it. Inside ExamplePage.js we will add the following code- import React from 'react'
- export default function ExamplePage(props) {
- const { page } = props;
- return (
-
{page.title.rendered}
- )
- }
This code allows us to use the pages from the state to create links and routes. As you can see when you click on one of the links you will be navigated to the right URL.
Let’s add some styling to our App like so.