Strapping React.js on a WordPress Backend: WP REST API Example

In a rush? Skip to tutorial steps or GitHub repo & live demo.

Even the biggest companies in a given space need to adapt to survive. Apple with the iPod. Google with AdWords. You get the idea.

Another tech big fish, WordPress, has been keeping up with a recent trend—headless CMS—showing a will to stay relevant and evolve:

wordpress-rest-api

Every developer and their dog have something to say about WordPress, and it's not always flattering. Far from it. However, even its most avid detractors will be forced to notice this new feature, because it could transform the way we use the popular CMS.

WordPress Rest API is a huge step forward for frontend developers looking to combine the power of JavaScript tools like React.js with WordPress.

This is exactly what I want to do today with this demo of the WordPress REST API in the work. I'll try to find out if this is really a game-changer and to deconstruct the hype surrounding it.

I'll use WordPress as a backend, and WordPress REST API to feed data into a simple React e-commerce SPA:

  • Creating products with the WP Advanced Custom Fields plugin
  • Mapping custom fields to JSON payload
  • Consuming the JSON REST API with React
  • Rendering products in our store

Before we start, let's see what is the new REST API for WordPress and why you should care about it.

What is WordPress REST API?

WordPress itself doesn't need any introduction, but let's take a closer look at the recent WP REST API. Before we start sliding down the road of its evolution, let's get some definitions out of the way:

An API (Application Program Interface) is a set of protocols for building software applications. It defines the way information is shared between programs and structures the way different components of an application will interact with each other. A good API makes for easier program development by providing all the necessary pieces.

REST (Representational State Transfer) is an architectural style defining constraints on the way programs are made. When this architecture is met by web services we called them RESTful APIs or, simply, REST APIs.

JSON (JavaScript Object Notation) is a format for structuring data so that a large number of applications can read it. It makes interactions between something like, say, WordPress, and any kind of app convenient.

As of WordPress 4.7, these concepts have been applied to create the WordPress JSON REST API. It allows for a decoupled approach, effectively separating data (back) from views (front).

What does it mean for users?

From now on, WordPress can be used as a headless CMS.

This offers a whole new world of possibilities for developers, as the frontend of WordPress doesn't need to be "WordPress"—PHP-generated views. The ever growing numbers of frontend frameworks can now be hooked up to a WordPress backend to develop websites and applications.

wordpress-as-headless-cms

Monolothic CMS vs Headless CMS [source]

When it comes to WP REST API, benefits abound.

Don't only take my word for it, developers already using it are thrilled of this paradigm shift:

"I’ve been able to forget about some of the weaker aspects of WordPress and take advantage of some of its better features — such as revisions, a simple editing interface, and familiarity. I can then use any frontend framework to consume the REST API, and display the content in the form I choose, taking advantage of the great features of those JavaScript frameworks, without the hassle of WordPress theming."

Working alone on a small demo means that I still have to deal with it to get WordPress running. On a larger project with a bigger team though, frontend developers could work in the language of their choice (without ever touching PHP) even if all the data is managed with WordPress on the backend. JSON magic at work right here.

Easier applications & using React.js

WordPress REST API makes it easier to connect to apps. A custom looking mobile app can now more easily than ever not only read WordPress data, but also create, edit and delete that data.

Many have started to use WordPress in "weird places", as in applications where it would have been a pain to work with a few years ago.

As for us? We chose React for this demo because, well, we've been talking too much about Vue recently. Jokes aside, we do want to keep our content diversified, and React still is one of the best frameworks out there: flexible & reusable component system, Facebook-backed open source project, efficient workflow with JSX, etc.

Enough talking; time to get practical.

WordPress with React.js: JSON REST API example

Now we'll use WP REST API in order to put together a full JAMstack.

Our office is going crazy over cryptocurrencies right now (our content crafter François wearing the Bitcoin evangelist hat), so we thought of setting up a Bitcoin gear shop for all cypherpunks out there. Until Snipcart integrates Bitcoin as a payment method, we'll help the community with content!

All you need to follow this tutorial is a Snipcart account (forever free in test mode) and a WordPress instance running.

1. Creating products with custom fields in WordPress

Let's jump right into the WordPress admin dashboard.

We'll be using the ACF (Advanced Custom Fields) plugin to start building our demo store.

This plugin allows you to add custom fields to native WordPress entities such as posts. It's thoroughly tested, stable and gives us a kick start to add custom data to pages.

Let's declare these custom fields. We'll need a price, a description, and an image.

declaring-wordpress-custom-fields

Now that we can add custom data to our posts in WordPress, let's use them to create three products.

Here are ours:

creating-products-posts-wordpress

2. Mapping custom fields to the JSON payload

Since we're building a React SPA with the JSON API, we'll need to use our JSON crawler to make Snipcart products validation work.

Our products attributes will have to be at the top level of the returned object.

So we'll craft a small plugin that will do this mapping.

Move to your wp-content/plugins folder and create a new Snipcart one.

In it, generate a snipcartplugin.php file and use the following code:

<?php
   /*
   Plugin Name: Snipcart
   Plugin URI: https://snipcart.com
   Description: Create your products directly in WordPress
   Version: 1.0
   Author: Geeks at Snipcart
   Author URI: https://snipcart.com
   License: MIT
   */

    function snipcart_add_json() {
        register_rest_field( 'post', 'price', array(
            'get_callback' => function( $post ) {
                return get_field('price');
            }
        ) );

        register_rest_field( 'post', 'description', array(
            'get_callback' => function( $post ) {
                return get_field('description');
            }
        ) );

        register_rest_field( 'post', 'image', array(
            'get_callback' => function( $post ) {
                return get_field('image');
            }
        ) );
    }    

    add_action( 'rest_api_init', 'snipcart_add_json' );
?>

What we're doing here is using the rest_api_init WordPress hook to register new rest fields.

These fields are defined in the get_callback function by using the Advanced Custom Fields function get_field. So, for each of our attributes, we get the associated custom field value and simply return it in the top level object.

3. Consuming the JSON API with React

Want to test everything right now? Hit your server for a test at: /wp-json/wp/v2/posts.

You should see all your posts with the proper custom fields mapped.

Time to add that React SPA to the mix now!

We'll be using the create-react-app module to scaffold it.

Go ahead and create your project, then fire up your favorite editor with the following lines:

create-react-app snipcart-wp cd snipcart-wp/

For our logic, we won't be crafting a full blown component. We'll simply be using the App.js created in the scaffolding.

First, let's make a constructor to instantiate our state:

constructor(props){
    super(props);

    this.state = {
      products: [],
      dataRoute: {YOUR_JSON_ROUTE} 
    }
}

Next, let's use React's lifecycle hook componentDidMount to fetch our data:

componentDidMount(){
    fetch(this.state.dataRoute)
        .then(res => res.json())
        .then(products => this.setState((prevState, props) => {
            return { products: products.map(this.mapProduct)};
        }));
}

Then, let's add the mapProduct function used in the map so we keep the code readable and separate concerns properly.

  mapProduct(product){
    return {
      id: product.id,
      price: product.price,
      image: product.image,
      name: product.title.rendered
    }
  }

Here we go! Once the component is loaded, it'll fetch the data and put it in the desired format in our this.state.products variable.

4. Rendering our products

In the same App.js component, let's re-implement our render function so it reflects our needs.

render() {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>Welcome to React</h2>
        </div>
        
        <div className="products">

          {this.state.products.map((product) => 
            <div className="product" key={`product-${product.id}}`}>

              <img src={ product.image } alt={ product.name } className="product-image"/>
              <p>{ product.name }</p>

              <button className="snipcart-add-item"
                data-item-name={ product.name }
                data-item-id={ product.id }
                data-item-image={ product.image }
                data-item-url= { `${this.state.dataRoute}/${product.id}`}
                data-item-price={ product.price }>
                Buy it for { product.price } $
              </button>

            </div>
          )}
          
        </div>
      </div>
    );
}

Here we iterate through our products with the map function and design a buy button for each one.

Only pieces missing now are Snipcart's necessary scripts.

We'll put them directly in the /public/index.html/ file at the end of the body tag:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>

<script src="https://cdn.snipcart.com/scripts/2.0/snipcart.js" data-api-key="{YOUR_API_KEY}" id="snipcart"></script>

<link href="https://cdn.snipcart.com/themes/2.0/base/snipcart.min.css" rel="stylesheet" type="text/css" />

Start the app with npm run start and you should have your products rendering directly on your homepage!

Ours: react-wordpress-products

It's important to keep in mind that this isn't really SEO friendly as the content won't be crawled by search engines. You could use the same process shown here with Vue to make sure it is.

WordPress REST API with React live demo

You can now browse our demo website, view product details and add them to the cart:

See GitHub code repo

See WP + React live demo

Please note that we don't sell all that awesome Bitcoin gear for real. Here's where you can really purchase the keychain, the cap and the t-shirt.

Closing thoughts

The way we are loading posts at the moment creates some overhead since we won't use all the information we receive. In fact, this might be one of the downsides of REST APIs in general. If we wanted to get only relevant data for our cart we could have created a full blown plugin that only serves products information in the JSON and nothing else.

Otherwise, for an inexperienced WordPress user like me, it has still been great to discover this new tool. It took me around two hours to build the demo and I assume it would be way quicker for a more seasoned WP developer.

It certainly is a step forward to be able to work with a JavaScript framework on top of a WordPress backend. The React part of the demo was a delight, always nice to play with it!

I have to mention that I'm not sure that I would suggest WordPress REST API over other systems that are specifically made as headless CMS and feel a bit less bloated. I would really like to know what you guys think about this, so hit the comment section!

To learn more about WP REST API you can find the documentation here, or a thorough white paper by Human Made, here.


If you've enjoyed this post, please take a second to share it on Twitter. Comments, questions? Hit the section below!

Suggested posts: