In the last installment of our REST API App series, we started looking at the front end part of the puzzle and selected React as the solution we’d be running with. The reasons why were simple: it’s speedy, well-documented, and enjoys the support of one of the largest players in the business, Facebook.
In order to check that we could get WordPress and React talking to each other, we downloaded the React Starter Kit locally and cobbled together a quick API call to display some arbitrary data from our local WordPress install.
Though our test worked, we didn’t exactly go to town on the details of how it was working. This time around, we’ll set that right with a more structured overview of putting together a simple React application and using it to display data.
Let’s start with an overview of what we’re up to.
What We’re Trying to Build
We’ll be taking our inspiration here from Per Harold Borgen’s excellent introductory React article. If you’re coming to React cold, it’s also well worth checking out his React.js in 8 Minutes piece before going any further.
We’ll be looking to put together a super simple, single-page app with three main moving parts: a random Thoreau quote (served up by WordPress), a suitable picture to accompany it, and a button that enables you to load another random quote.
Rather than thinking about this in terms of templates, we’ll be using the concept of components in React to organize things. Looked at in those terms, we can break the picture above into four useful sub-components:
- ThoreauApp: The component that will house everything.
- Picture: Where our image will live.
- Quote: Where we’ll be displaying the best of Thoreau’s musings.
- RandomButton: An opportunity for users to load fresh wisdom.
Now, let’s take it from the top and put together our first component.
Creating Our First Component
Just a quick reminder here – we’re working in an index.html page in the root directory of our local http://www.thoreauapp.dev/ site. The React Starter Kit is in the same directory, and we’re including relevant files in our header. You’ll also notice an imaginatively named empty <div> on the page which we’ll load our content into:
<!-- DOCTYPE HTML --> <html> <head> <meta charset="UTF-8" /> <title>React Thoreau App</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script> <script src="build/react.js"></script> <script src="build/react-dom.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script> </head> <body> <div id="content"></div> </body> </html>
We call the createClass method on the React object to define our first component. As you can see below, we’re also passing in a specification object:
var ThoreauApp = React.createClass({ render: function(){ return (<div><p>A foolish consistency is the hobgoblin of little minds.</p></div>); } });
The specification object is where we’ll be defining a number of things shortly, but we’ll kick things off by creating a basic render method. This is what React will use each time it redraws the contents of the component.
If you excitedly refresh your browser page at this point, you’ll be greeted (sadly) with absolutely nothing. That’s because we’ve only defined a potential component at this point, we haven’t brought it to life yet. Let’s take care of that now by using ReactDOM.render:
ReactDOM.render(<ThoreauApp />, document.getElementById('content'));
What we’re doing here is telling ReactDOM.render two very important pieces of information:
- The component it should render.
- The area on the page it should render it within.
A quick refresh of the page, and we’re greeted with the following inspiring sight:
Before we go any further, let’s briefly take stock of what’s going on so far.
What Just Happened?
It’s worth actually looking at the code in its entirety at this stage, just to be crystal clear about what we’ve actually done:
- We loaded the relevant React libraries.
- We have a defined area on the page to load our React content into.
- We worked inside <script> tags to write our JavaScript/JSX.
- We defined a component and gave it a render function.
- We instantiated our component.
Now that we know roughly what’s going on, let’s take a brief detour to fancy things up visually.
Sprinkling in Some Style
Our on-screen results so far are less than inspiring. It would be nice to throw at least some color and typography into the mix at this stage. But how? The simple answer here is by using inline styles.
CSS purists will doubtless be clutching their pearls at the mere thought of this, but that horror pales in comparison with the despair others will feel when confronted with the modern React CSS landscape.
There are, admittedly, all sorts of clever modular solutions (such as Radium) out there, but we’re looking to keep things as simple as possible here. With that in mind, we’re going to throw some quick styles into the render function and get on with our lives:
var ThoreauApp = React.createClass({ render: function(){ var thoreauAppStyle = { backgroundColor: 'ffde00', color: '#333', padding: 20, width: 550, margin: '0 auto', fontFamily: 'Georgia', fontSize: 22, fontWeight: 'bold' } return (<div style={thoreauAppStyle}><p>A foolish consistency is the hobgoblin of little minds.</p></div>); } });
All of that leads to the following result:
We won’t be winning any design awards, but it’s enough to establish that we have some control.
With that brief detour out of the way, let’s break things out into components a bit more thoroughly.
Adding Child Components
Now that we’ve got something on the page – and a vague idea of one way to style elements – let’s get a bit more organized. We’ll start by creating our next two components. As you can see, the placeholder text is moved into Quote, and there’s a placeholder image in play now courtesy of lorempixel:
var Picture = React.createClass({ render: function(){ return ( <div> <img src='http://lorempixel.com/550/350/' /> </div> ); } }); var Quote = React.createClass({ render: function(){ return ( <p>A foolish consistency is the hobgoblin of little minds.</p> ); } });
Again, we need to actually call these – this time by updating what we return from the ThoreauApp component:
return ( <div style={thoreauAppStyle}> <Picture /> <Quote /> </div> );
A quick refresh and we see the following:
It’s looking a lot better! There are a lot of placeholders knocking around so far, though. Let’s look at bringing in some data.
A Quick Word About Data In React
Data generally in React can be handled as either ‘state’ or ‘props’. These can be slippery concepts to grasp, so a close review of Thinking in React and the relevant documentation is recommended. The beauty of state in React is that changes to it will fire automatic updates to the relevant components on-screen down the line.
Once state arrives in the form of interactions, the general idea is that you want it to be handled once, as high up the component chain as possible, and then move data around as props thereafter. That’s broadly the approach we’ll take when we hook up the REST API and introduce a button for users to play with next.
Talking To The WordPress REST API
Let’s get down to business! The first thing we’ll do is make our app aware of where it can get data from:
ReactDOM.render(<ThoreauApp dataURL="http://walden.dev/wp-json/wp/v2/posts" />, document.getElementById('content'));
Before we look at loading the data, we’ll make sure we’re starting with a clean slate on each page load. getInitialState will be called once automatically on load and can be used to clear the decks:
getInitialState: function() { return {data: [], selectedQuote: ''}; },
Then we’ll use componentDidMount to actually make the call to our WordPress API. In this instance, we’re using jQuery to make the actual AJAX request. It’ll store the results of the request inside the component using setState:
componentDidMount: function() { $.ajax({ url: this.props.dataURL, dataType: 'json', cache: false, success: function(data) { this.setState({data: data}); this.chooseRandomQuote(); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); }.bind(this) }); },
We’ll also call another function here to pick out a random quote from the result set and assign it to a particular state:
chooseRandomQuote: function () { var randomNumber = Math.floor(Math.random() * this.state.data.length); var selectedQuote = this.state.data[randomNumber]; this.setState({selectedQuote: selectedQuote.content.rendered}); },
We now need to feed that information into our Quote component. We’ll do that by passing it in as a prop called quote:
<Quote quote={this.state.selectedQuote} />
And then pick it up and display it inside the component:
<div>{this.props.quote}</div>
A quick refresh shows that we’re almost there:
Let’s finish things off.
Displaying External HTML Content and Adding Interaction With a Basic Button
The eagle-eyed will have spotted that we have big dirty paragraph tags sitting there staring at us. This is actually by design in React, to avoid cross-site scripting risks. We can get around it quickly by using the excitingly named dangerouslySetInnerHTML to get the job done:
<div dangerouslySetInnerHTML={{__html: this.props.quote }} />
Our final task for today is adding a bit of basic interaction. We’ll do this in the simplest way possible by adding in a quick button back in ThoreauApp that can call our earlier state-changing chooseRandomQuote function:
return ( <div style={thoreauAppStyle}> <Picture imageURL='http://lorempixel.com/550/350/' /> <Quote quote={this.state.selectedQuote} /> <button onClick={this.chooseRandomQuote}>Get more wisdom!</button> </div> );
Thanks to the magic of React, our button will now cause a re-render of the content (using the data it already has loaded) with a fresh quote each time it’s pressed. Our work for today is done!
Conclusion
We’ve necessarily kept things as stripped down as possible in the example above, but hopefully it’s enough to walk you through the basics of React, and offer several potential jumping off points for further self-study.
We’ve come a long way from the first installment in our series! To recap, what we have so far is a one-page React app that:
- Is split out into components.
- Loads data from the WordPress REST API and displays a random result.
- Enables users to display fresh content at the touch of a button, without needing further page reloads.
Stay tuned for part five soon, where we’ll look at adding some stylish UI touches and experimenting with custom endpoints.
As always, we’d love to hear from you if you’re following along at home. Get in touch via the comments section below and share your thoughts!
4 Comments