WP REST API Part 1: Creating a Mobile App with WP-API and React Native

#
By Jeff Gould

The WP REST API is a WordPress plugin that intends to be eventually integrated into WordPress’ core as another (big) step towards transforming WordPress from a blogging platform/CMS into a fully fledged application framework. While WordPress is currently a great choice for a broad range of applications, one area where it currently falls short is providing an easy way for external programs to communicate with the WordPress database. This is what the WP-API team is aiming to fix.

In this series, I’ll be showing you how to use the WP REST API plugin and employ WordPress as a datasource for a simple React Native mobile app. The REST API plugin is still in beta and is liable to change in the near future but the v2 API is what will eventually become a part of WordPress so it makes sense to start looking at it and building with it now.

What We’re Building

To start, we’re going to be building a simple iPhone app using React Native called ‘Deep Thoughts’ which will pull posts from a WordPress install via the WP REST API and display a random ‘deep thought’ to the user every time they touch a button. We’ll start with the “minimum viable product” or MVP version of this app and add functionality throughout the series by digging deeper into the capabilities of the WP REST API.

Getting Started

To get things going, you’re going to need a fresh WordPress install running locally at http://deep-thoughts.dev, as that’s the URL that I’ll be using in all of the code samples. You’ll also want to create some posts or download this export which contains some of my favorite Deep Thoughts by Jack Handey.

Next, you’ll want to install the WP REST API plugin from the plugin repository and activate it. Make sure that you’ve got “pretty permalinks” set up and working correctly as the REST API uses custom rewrite rules. If you’ve set up your site at http://deep-thoughts.dev, you can check that everything is working correctly by pointing your browser to http://deep-thoughts.dev/wp-json/wp/v2/posts/ – you should see some JSON data, but if you get a 404 you’ll want to make sure that the WP REST API plugin is installed and that permalinks are working properly.

jsonview

That’s just about all there is to it on the WordPress side of things. There’s quite a bit going on behind the scenes, but the WP REST API makes it that easy to get simple API access to your WordPress install. Now let’s put it to use!

Taking WordPress Beyond the Web

While you can certainly use your new REST API to power a web-based application , the API really shines when you use it off the web, so we’ll be creating a simple iPhone app using Facebook’s React Native framework.

To keep this short, I’ll assume you’ve at least followed the getting started guide on the React Native website and are able to run the boilerplate app which we’ll be using as our starting point. Create a new project by running the following from your CLI:

$ react-native init DeepThoughts

Now open the created project in XCode and run the app in the iPhone simulator. You should now be seeing the boilerplate app which looks like this:

RCo7nHi

Now you can open up the index.ios.js file in your favorite text editor and replace the boilerplate code with a basic template that I’ve created for the app:

Now you can switch back to your iOS simulator, hit ⌘R and you should see the app update to look like this: (Hint: if ⌘R doesn’t work, hit ⇧⌘K to enable the hardware keyboard and try again)

mcsu0Q8

We’re currently just using some mocked up data, so let’s see about hooking up our WP JSON API. As outlined earlier, I’m running my API at http://deep-thoughts.dev, and I’ll want to get some posts to use in the app, which I can get by performing a GET request to the endpoint at /wp-json/posts/. I’ll start by adding a variable under the MOCKED_DATA variable called REQUEST_URL:

var REQUEST_URL = 'http://deep-thoughts.dev/wp-json/wp/v2/posts/';

Now we’ll need to get the data from our API, which React makes quite simple with it’s built in fetch function. We’ll add two functions right after the getInitialState function: componentDidMount which is automatically called by React when the app has finished loading, and our fetchData function which will get the data from our API:

componentDidMount: function() {
    this.fetchData();
},
fetchData: function() {
    fetch(REQUEST_URL)
    .then((response) => response.json())
    .then((responseData) => {
        this.setState({
            thought: { title: responseData[0].title.rendered, content:responseData[0].content.rendered },
        });
    })
    .done();
},

All that’s happening there is when componentDidMount is automatically called by React Native, it is in-turn calling our fetchData function which is grabbing the JSON data from our WP REST API endpoint, parsing it as JSON data and then updating the application’s state by populating the thought variable with an object containing the title and content of the first item in the array of posts that it received from the API. React handles everything that needs to be changed in the UI whenever the application’s state is updated, so when the app first loads we’ll still see our mock data which will be replaced by the real data that has been pulled from the API once it’s been downloaded and parsed.

Here’s the updated code:

Once you’ve updated and saved index.ios.js you can return to your iOS simulator and hit ⌘R again to update it with the new code. You should see the mocked data at first and then you’ll see the app update with the latest post from your WordPress install – pretty neat!

9I18v5q

The only problem is that WP REST API seems to be applying the the_content filter to the post content which is adding html and entity codes, but React-Native is displaying this as plain text. Fortunately, WP REST API provides the rest_prepare_post filter which will allow us to modify its output. Adding the following code to a utility plugin or your theme’s functions.php file should fix this up:

add_filter( 'rest_prepare_post', 'dt_use_raw_post_content', 10, 3 );
function dt_use_raw_post_content( $data, $post, $request ) {
    $data->data['content']['plaintext'] = $post->post_content;
    return $data;
}

Now you’ll need to update the React Native code to use the new plaintext content, so change the fetchData function to set the thought variable’s content property to use responseData[0].content.plaintext instead of responseData[0].content.rendered

fetchData: function() {
    fetch(REQUEST_URL)
    .then((response) => response.json())
    .then((responseData) => {
        this.setState({
            thought: { title: responseData[0].title.rendered, content:responseData[0].content.plaintext },
        });
    })
    .done();
},

Refresh your iPhone simulator and things should be looking much better now:

Kpq0ZvS

So far this is pretty cool and the WP REST API has made this a much easier process by playing so nicely with React Native. But just showing the latest post is hardly something to write home about. What if we want to show a random “Deep Thought” from our database? WordPress provides a way to do this when using WP_Query() or get_posts() by allowing you to pass the orderby parameter with a value of rand which will return a randomly ordered selection of posts*.

Likewise, the WP REST API allows us to structure queries in a similar way by adding query parameters to the endpoint URL. So all we have to do to get a random post is update our REQUEST_URL variable to include ?filter[orderby]=rand at the end. We’re also currently grabbing more posts than we need, so let’s set filter[per_page] to 1 since that’s all we need. Our updated REQUEST_URL should now look like this:

var REQUEST_URL = 'http://deep-thoughts.dev/wp-json/wp/v2/posts/?filter[orderby]=rand&filter[per_page]=1';

Once you’ve made this change, go ahead and hit ⌘R in your iOS simulator and you should see it load a random post every time you refresh. Now let’s make the ‘hmmmm’ button work so that we don’t have to refresh the app every time we want to see a new “deep thought.” React makes this relatively simple, all we have to do is add an onPress attribute to the touchableHighlight element in the template that calls our fetchData function again. That should look something like this:

<TouchableHighlight
    style={styles.button}
    underlayColor='#ccc'
    onPress={this.fetchData}
>
    <Text style={styles.buttonText}>Hmmmmm...</Text>
</TouchableHighlight>

Here’s the final code for the app where I’ve also made some small updates to show a ‘loading’ message when we’re fetching a new “thought” from the server as well as when the app is initially loading, instead of the mock data:

And here’s what our app looks like in action:

DeepThoughtsApp

As you can see, the WP REST API has made it incredibly easy to use WordPress data with pretty much any app development framework that can send HTTP requests and parse JSON data. While we’re using React Native here, our API can communicate just as simply with web frameworks like Angular and Ember, or even native mobile frameworks for iOS, Android, and Windows Phones.

Our DeepThoughts app is simple right now, but we’ll be exploring the capabilities of the WP JSON API in later installments of this series by adding more features and interactivity to it. What features would you like to see added to the DeepThoughts app, and what parts of the WP REST API would you like to explore next? Let me know in the comments!

*Note: filter[orderby]=rand is bad for performance as it isn’t reliably cacheable on any level. In fact, some hosts and plugins specifically disable using orderby=rand to improve performance, so if you’re following along and your query isn’t working properly, that might be why. The use of orderby=rand here is for demonstration purposes and in the next installment of this series we’ll look at ways of extending the our REST API to more efficiently provide a random post.

About the Author

Jeff Gould

Jeff is a problem solver at heart who found his way to the web at an early age and never looked back. Before Delicious Brains, Jeff was a freelance web developer specializing in WordPress and front-end development.