React Ships with WordPress

Ever since WordPress 5.0, React (or an abstraction of it), now ships with WordPress.

WordPress takes the entire React and ReactDOM libraries and exports them onto a global window object named wp.element.

This is a little different from how most React apps work.

In a Normal React App We Import React, in WordPress We Don’t

Normally, with a React app or project, you import React at the top of each file that uses React. On your main index page you would likely import ReactDOM as well.

// A Normal React App
import React from "react";
import ReactDOM from "react-dom";
import MyComponent from "./components/MyComponent";

ReactDOM.render(<MyComponent />, document.getElementById("root"));

In WordPress we do not import React or React DOM because they are made available in the global wp.element object.

So one important difference when you go to include React in your WordPress project is you do not import it into your files.

Another difference between using React normally and in a WordPress theme or plugin has to do with tooling.

Using WP Scripts Instead of Create React App

If you have built React apps before you probably use Create React App or a similar bundle of tools to run your development server and build your production code.

This tooling does not work as well for WordPress because React is loaded in the global window object wp.element rather than bundled with the code. Create React App does not officially support loading React from an external source without ejecting so that is not necessarily the best option for tooling.

Luckily, the WordPress team built a wp-scripts package based off of the react-scripts package used with Create React App.

WP Scripts includes develop, lint, test and build commands by default. You can also extend it with your own custom webpack config if you want to do something special, like compile SASS for instance.

We will look at how to setup WP Scripts below, but first let’s get our basic theme setup with React loaded on the front end.

Enqueuing React in Your Theme

To make sure React is loaded, you will simply add wp-element as a dependency of your own JavaScript file.

The following would go in your functions.php file.

// Enqueue Theme JS w React Dependency
add_action( 'wp_enqueue_scripts', 'my_enqueue_theme_js' );
function my_enqueue_theme_js() {
  wp_enqueue_script(
    'my-theme-frontend',
    get_stylesheet_directory_uri() . '/build/index.js',
    ['wp-element'],
    time(), // Change this to null for production
    true
  );
}

For this to work you will need a file located at /build/index.js. WP Scripts will create this for us when we run the build command

Now wp.element will load on the front end of your theme.

How to Setup WP Scripts

Setting Up WP Scripts involves two steps: 1) install wp-scripts; 2) add the scripts to your package.json file.

If you have not setup a package.json file yet run the following command from the root of your WordPress theme:

npm init

You can either press return for each of the prompts or add in your own custom information.

Once your package.json file is created, run the following command:

npm install @wordpress/scripts --save-dev

This will download WP Scripts to your node_modules and make it available to use in the command line.

We can now do something like this:

wp-scripts start

However, to make this more universal and easy to use, we will map the WordPress Scripts to NPM scripts.

Open up your package.json file and replace the current "scripts" settings with the following:

{
  "name": "myreacttheme",
  "version": "1.0.0",
  "description": "My WordPress theme with React",
  "main": "src/index.js",
  "dependencies": {},
  "devDependencies": {
    "@wordpress/scripts": "^5.1.0"
  },
  "scripts": {
    "build": "wp-scripts build",
    "check-engines": "wp-scripts check-engines",
    "check-licenses": "wp-scripts check-licenses",
    "lint:css": "wp-scripts lint-style",
    "lint:js": "wp-scripts lint-js",
    "lint:pkg-json": "wp-scripts lint-pkg-json",
    "start": "wp-scripts start",
    "test:e2e": "wp-scripts test-e2e",
    "test:unit": "wp-scripts test-unit-js"
  },
  "author": "",
  "license": "1 GNU V2+, MIT"
}

If you do not need all of these, you can shorten it to just the start and build commands. However, the others can be useful to have as well.

Now we are able to run the following:

npm start

And it will call off the WP Scripts start command. This will look for any file imported from src/index.js and build it out to build/index.js any time a file is changed.

The build command does the same thing, but only once and does not watch for changes.

Adding React to a Custom Page Template

More and more of the display of content is controlled in WordPress through blocks. Blocks in WordPress are also based on React, but they are a little ecosystem in and of themselves and outside the scope of this particular blog post.

Here we are going to focus on adding some React to a custom page template. While everything we do could be built into a block, there are still going to be times when building a custom page template React serves as useful.

For this purpose I am going to make a Child Theme of the 2020 Default WordPress Theme. My basic theme structure looks like this:

/build
/src
/-- index.js
functions.php
package.json
page-react.php
style.css

These are about the minimum requirements we will need.

Without too much explanation, here is the code for the functions.php file and the style.css file.

Here is the functions.php file:

<?php
add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_styles' );
function my_theme_enqueue_styles() {
 
  $parent_style = 'twentytwenty-style'; 
    
  wp_enqueue_style( $parent_style, get_template_directory_uri() . '/style.css' );
    
  wp_enqueue_style( 'child-style',
    get_stylesheet_directory_uri() . '/style.css',
    [ $parent_style ],
    time() //For production use wp_get_theme()->get('Version')
  );

  wp_enqueue_script(
    'my-theme-frontend',
    get_stylesheet_directory_uri() . '/build/index.js',
    ['wp-element'],
    time() //For production use wp_get_theme()->get('Version')        
  );
  
}

And then the style.css:

/*
 Theme Name:   Twenty Twenty Child
 Description:  Twenty Twenty Child Theme
 Author:       Zac Gordon
 Author URI:   https://javascriptforwp.com/
 Template:     twentytwenty
 Version:      0.9.0
 License:      GNU General Public License v2 or later
 License URI:  http://www.gnu.org/licenses/gpl-2.0.html
 Text Domain:  twentytwentychild
*/

We also have a very simple custom page template page-react.php that looks like this:

<? php
/**
 * Template Name: React Template
 */
get_header();
?>

<main id="site-content" role="main">
	<article class="post-2 page type-page status-publish hentry">
		<?php get_template_part( 'template-parts/entry-header' ); ?>
		<div class="post-inner thin">
			<div class="entry-content">				

				<div id="react-app"></div><!-- #react-app -->

			</div><!-- .entry-content -->
		</div><!-- .post-inner -->
	</article><!-- .post -->
</main><!-- #site-content -->

<?php get_template_part( 'template-parts/footer-menus-widgets' ); ?>
<?php get_footer(); ?>

This is basically a simplified page.php template from the parent theme with a div containing the id react-app added for us to load our React code into.

It is possible to build larger sections of a theme with React, but we are going to just focus on loading it on a single template here.

To complete this setup process, create a new page and select the “React Template” as the page template.

Writing Our React

Inside of our src/index.js file we can start writing our React code and adding it to the page.

We will build on this over the course of this series, but for now we will add a simple component that lets you click a button to increase the number of votes for something.

const { render, useState } = wp.element;

const Votes = () => {
  const [votes, setVotes] = useState(0);
  const addVote = () => {
    setVotes(votes + 1);
  };
  return (
    <div>
      <h2>{votes} Votes</h2>
      <p>
        <button onClick={addVote}>Vote!</button>
      </p>
    </div>
  );
};
render(<Votes />, document.getElementById(`react-app`));

A few important things of note here:

  1. We are not importing React or ReactDOM on the page, but rather getting what we need from wp.element, which is already loaded for us.
  2. ReactDOM.render() is also included in wp.element
  3. Currently the state is not being saved in WordPress, but we will change that in future articles

From here you can start writing whatever React you want, as well as breaking code out into separate files and importing them as needed.

This is hopefully enough to get you up and running with adding React to your WordPress themes.

Setting Up Webpack Externals to Use Libraries Importing React

Most React packages that you use will be used to having React bundled with the final code and will include import React from "react" and things like that in their own code.

This will not work with WP Scripts by default. To get this to work we have to extend WP Scripts with our own webpack.config.js file and define React and ReactDOMs as external resources that will be available outside of the bundled code.

To do this, create a new webpack.config.js file in the root of your theme and add the following:

const defaults = require("@wordpress/scripts/config/webpack.config");

module.exports = {
  ...defaults,
  externals: {
    "react": "React",
    "react-dom": "ReactDOM"
  }
};

This will get the default configurations from WP Scripts and add them as the fallback configurations for Webpack. Then we can add in our customization of defining “react” and “react-dom” as being available as externals.

This will prevent errors from occurring when using third party React libraries that expect React to be imported.

Next Steps

From here can hopefully start building all the React you need for your themes. You may need to load your React in different places, like the header, sidebars or footer but the process is pretty similar.

In future articles we will go into more things you can do with React in WordPress Themes! You can find the main repo for this series here.

Please share how you’re using React in your WordPress themes and projects!