How to use React with the WordPress REST API

I remember back when I learned how to develop for WordPress, I spent weeks in the Codex, learning the template hierarchy, the template tags, and so on. The Codex was like my Hitchhiker’s Guide To The Galaxy: they might as well have printed “DON’T PANIC” on the front, because it kept me learning at a comfortably steady pace.

These days it feels more like I’m stuck in Dictionopolis from The Phantom Tollbooth. Reading through documentation for new technologies is like I’m just staring at heaps of words trying to force my brain into understand just what “ComponentWillUnmount” means in human English.

The trouble is that as we get new technologies, documentation tends to lag behind development. The docs I’m seeing these days for things like the WordPress REST API or React don’t have that same friendly quality that the Codex did, yet.

Fortunately, we can turn to trailblazers: people who have gone before us, figured out how to use it, and then turned around and shared that knowledge. If it weren’t for Wes Bos, I wouldn’t even be writing this article. His “React for Beginners” course recaptured that same steady, comfortable way of learning for me.

Eventually, I learned how to convert a plugin from using jQuery to using the WordPress REST API and React JS. I learned a lot along the way, so here’s my take, in human English:

Getting to Know the Lingo is the Hardest Part

When I started looking around for a “beginner’s guide to the WordPress REST API,” I was confronted with a horde of new vocab terms: “route,” “endpoint,” “RESTful,” “CRUD,” and so on. In short, I fell down a rabbit hole of foundational knowledge when all I wanted was practical knowledge. I wanted to figure out how to use it.

After doing a lot of reading, I realized there were only two terms I had to figure out: “routes” and “endpoints.”

The crazy thing is, these terms are not as technical or complicated as they sound. A route is a URL. An endpoint is a PHP function. Here’s how they work together to get data from WordPress.

How Routes and Endpoints Work

Normally, we use PHP to get data from the WordPress database. The trouble with that is that it’s a server-side thing. If any data changes, you’ll have to reload the page to see it.

The REST API opens things up to the front-end: we can get data from WordPress using a HTTP connection (a URL) instead of using PHP. This way, you can use JavaScript to get data from the WordPress database without reloading the page.

This URL that gets and retrieves data is called a route. It’s a special URL that you have to register. WordPress comes with a few pre-registered, but the real power is in registering custom routes. This was my key misconception number one: just like custom post types or meta, you can register as many routes as you want.

My key misconception number two was thinking that these routes can only return specific types of data. FALSE. A custom route can return whatever data you want.

When you use register_rest_route to define what the route will be, you also give it a PHP function to run when the route is loaded. That PHP function is known as the endpoint. This leads me to key misconception number three: I assumed using the REST API meant you had to use JavaScript 100% of the time.

When the route (URL) is loaded, WordPress calls the endpoint (PHP function that returns data).

Global State with React JS Makes it Easy to See What’s Going On

If you read up on React and similar JavaScript frameworks, there’s a lot of talk about “state.”

All “state” means, really, is “what’s going on in this application right now?” Is the modal window open or closed? Which slide in the slideshow is currently displayed? State keeps track of things that change.

This means that you can handle state whether you’re working in jQuery or in React (key misconception number four, if you’re keeping track at home).

The State pane in the React panel
The State pane in the React panel shows the global state for the whole application.

The key difference is that React centralizes all of the things that can change into one place, the state object. Grouping these details together makes it much easier to see what’s going on across the entire application.

It also makes it much easier to change. With the React Developer Tools in Chrome, you get a new tab in the Dev Toolbar called React, where you can inspect and manually change the state to see how it effects your project.

Getting Started with React and the WordPress REST API

Actually getting started with React and the WordPress REST API can be a challenge, even if you’re familiar with both technologies.

For example, I wanted to refactor the Admin Command Palette plugin that I and a couple other guys at my job made. It’s a universal WordPress admin search modal. The original version runs on jQuery and works decent, but has a fatal design flaw: it can’t scale at all.

The Admin Command Palette search in action.

When we built it, I had looked at other plugins that used AJAX to power the search, and they seemed slow. I had the bright idea to localize all the search data to get around this. While that’s not terrible when you’re dealing with less than 500 posts, try doing it with 5,000! All that data was echoed out in the footer and made the WP-Admin take forever to load.

I had cleverly created the exact problem I was trying to avoid. But I’m a smarter developer today (which is what all developers tell themselves), and figured rewriting it in React would make it cleaner and faster.

When I first got started, I fiddled with React for a bit, but was having a hard time figuring out how exactly to connect it to the API. So I went out and found another trailblazer. Go Pangolin created a boilerplate React / WP API plugin called WP-Reactivate that was exactly what I needed.

I was immediately drawn to their Fetch API example, which demonstrates the coupling from React to the WordPress REST API. Eventually, I wound up with this:

fetch(`${acp_object.api_search_url}/?command=${}`, {
            credentials: 'same-origin',
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'X-WP-Nonce': acp_object.api_nonce,
            .then(response => response.json())
                (json) => this.setState({
                    results: json.results,
                    count: json.count,
                (err) => console.log('error', err)

A few notes on what we’re looking at here:

  1. acp_object is a localized script (data that you set up with PHP but make available for JavaScript)
  2. ${acp_object.api_search_url} is the WP API Route that I registered using register_rest_route.
  3. ?command=${} is important: I used this to pass a parameter from my JavaScript into the PHP function, which I retrieved with get_param( 'command' );
  4. X-WP-Nonce is also important: with this, you make the connection from JavaScript to PHP secure.
  5. this.setState is where I take the data that came back from the PHP function and update the React application.

Debugging PHP through JavaScript

My last practical tip is on debugging. When you’re using React, it’s not always easy to see what’s wrong if you’re getting the wrong data back from your PHP function.

When I was refactoring the Admin Command Palette, the “XHR” tab (under Network in Chrome’s Web Inspector) proved invaluable. Here you can see the exact response as it comes back from PHP, before React intercepts it.

What this means is that you can use print_r() statements to test variables inside of PHP and you’ll see the output on the XHR tab. Yeah, it’s hacky as hell, but it works.

You could also add temporary parameters to the response data that gets sent back to React. In my example only a search results array and the total count get passed back, but when I was developing it, I threw in things like “post_args,” “search_filters,” or “command_type” all willy-nilly.

That’s what development is for. It’s a safe place to break whatever you need to in order to make your code better.

New Posts in your inbox

  1. Josh, thank you for writing up your experience! What I didn’t see was how much of an impact converting the plugin to react and the Rest API had on plugin performance and scalability. Have you seen enough of an impact to make the work worthwhile (apart from the value of learning something new)?