If you like this post, please check out my Courses and Online Bootcamps at JavaScript for WordPress.
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.
functions.php
<?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() //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')
);
}
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 id="react-app"></div>
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.
file: /src/index.js
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:
- 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. -
ReactDOM.render()
is also included inwp.element
- 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!
If you like this post, please check out my Courses and Online Bootcamps at JavaScript for WordPress.
Top comments (5)
Thanks for sharing.
Does it work with typescript ?
Haven't tried it, any reason you could think of that it wouldn't? Pretty sure it functions just like React anywhere else, since it's all still React under the hood :)
Hi Zac
Have followed this tutorial and everything seems to be working in the Terminal but nothing is rendering for me within the react-app element on the page. I have even cloned your repo and that is doing the same thing.
Any ideas?
A great useful post!