To Do: Create Your First React Application – Part I
React is a JavaScript library that is primarily responsible for handling the “view” component of a JavaScript single-page application. As it describes itself of the React homepage…
Lots of people use React as the V in MVC. Since React makes no assumptions about the rest of your technology stack, it’s easy to try it out on a small feature in an existing project.
React’s focus, first and foremost, has to do with rendering dynamic UIs in a manner that is visually appealing to the user. It is flexible enough that it can be used in a diversity of capacities and contexts. We have looked at React in previous entries. In what follows we will look at creating an introductory application using React and React related tools and libraries. One of the more ubiquitous tutorial applications that developers build when learning a new language or framework is the TO DO (To do) app. In terms of prevalence, it is probably second only to the “Hello, World” app which has been around since the dawn of programming. But the “To Do” application is popular because it covers a lot of the basics of how a language or framework handles a number of things. There must be a way to add a new “to do” so handling user input is involved. The same is true for displaying data, editing and saving data, and changing display state when data updates. All of these things are going to be important implementations in any application.
In what follows we will create the iconic “To Do” application in React and discuss some of the inner workings as we go along. We will take a deeper look into React components and how we can add some dynamic interactivity to our React applications in response to user actions — things like clicks and entering text in a text box — and updating our views accordingly.
JSX Compilation with Babel & Browserify
As we will see, React has its own programming language called JSX. It has been described as sort of like a mixture of JavaScript and XML and it is React’s own special easy-to-read abstracted syntax. JSX is not required to create React applications and you can write your React components in native JavaScript if you prefer. Because browsers do not natively understand JSX in order for your react application to run JSX needs get converted to native JavaScript.
The React website suggests that you utilize tools like Babel and/or Browserify (both of which run on Node.js). Babel is what is known as a transpiler. It mostly functions as a tool that takes code written in ECMAScript 6 (ES6) and converts it to ES5. As of 2015 this is still necessary because support for ES6 across all browsers is not widespread yet. Until support for ES6 is implemented across all browsers, tools like Babel will still be needed. Although many people think of Babel primarily as an ES6 to ES5 transpiler, Babel also comes with JSX support as well. You can merely run the Babel transpiler on your JSX files and they will be converted to native JavaScript that will be recognized by any browser circa 2015.
Browserify allows for Node.js style module loading in your client-side JavaScript. Like with Node, it allows you to import code in certain JavaScript files into other JavaScript files for better organization of your code.
Task Runners / Module Bundlers
For our sample code, we will be using task runners to handle our JSX conversion to native JavaScript. You may have heard of task runners like Grunt or Gulp, or module bundlers like webpack. We will be using webpack because it has, at least for the time being, become the utility of choice among the React community. If you are not entirely familiar with JavaScript task runners it would definitely be worthwhile to read the webpack documentation (or watch a few videos) on what it is and why you would want to use it. The more recent versions of React essentially require you to set up your tools before you work with JSX in React. In previous versions of React there was an easy extra <script> tag that you could add in your HTML to make it easy to implement JSX. However this has since been deprecated. If this seems daunting and you are already feeling overwhelmed, not to worry! We will walk through how to set everything up before we dive into React coding.
Setting Up
To start we need to set up our package.json and webpack.config.js files so that we can set up our tools to do JSXcompilation to native JavaScript. Create a new directory and then create a package.json file and add the following…
{ "name": "React", "version": "0.0.1", "description": "A React application...", "license": "MIT", "repository": { "type": "", "url": "" }, "homepage": "https://9bitstudios.com", "scripts": { "start": "webpack-dev-server --progress" }, "dependencies": { "react": "15.3.0" }, "devDependencies": { "webpack": "1.13.1", "webpack-dev-server": "1.14.1", "babel-core": "6.13.0", "babel-loader": "6.2.4", "babel-preset-es2015": "6.13.0", "babel-preset-react": "6.11.1" } }
Next, in this same directory, create a webpack.config.js file and add the following…
var webpack = require('webpack'); module.exports = { devtool: 'source-map', entry: __dirname + "/src/App.js", output: { path: __dirname + "/dist", filename: "App.js" }, watch: true, module: { loaders: [ { test: /\.jsx?$/, exclude: /node_modules/, loader: 'babel', query:{ presets: ['es2015', 'react'] } } ] }, devServer: { colors: true, inline: true }, plugins:[ new webpack.optimize.UglifyJsPlugin(), ] };
After this, let’s open a command prompt and run the following…
$ npm install
to install all of our modules that we will need for compiling ES6 and JSX. And that is all there is to it. Now that we have our tools installed and configured, we can dive into writing our application.
Writing a “To Do” Application
So let’s get started creating our “To Do” app. We will start out by creating our index.html file…
<!DOCTYPE html> <html> <head> <title>React</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <div id="content"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.0/react.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.0/react-dom.js"></script> <script type="text/javascript" src="dist/App.js"></script> </body> </html>
As we can see, we are going to include App.js, which will be a file that we generate in our task runner. Note too we are creating a
Next, create a folder called “src” and create a file called App.js in this folder. For this tutorial we are going to be breaking our components up into different modules so in our App.js file all we need to add for now is the following.
import {react} from 'react';
In the same directory as your App.js file, next create a file called “Todo.js”. In this file, we are going to need to create a React component/class that will represent each individual “to do.” Add the following code to this file…
import {react} from 'react'; class Todo extends React.Component { render() { return(<div>I am a to do</div>) } };
Pretty straightforward. This should look familiar as it is similar to our other earlier examples.
Now what we’re going to do is import this module into our App.js file. How do we do this? In our App.js file we just need to add the following…
import {react} from 'react'; import {Todo} from './Todo';
This will tell our code to import the “Todo” module from the “Todo” file relative to where “App.js” is located. With module loading in ES6 you can omit the “.js” from the file when you are importing modules.
So we are definitely well on our way but if we were to run this code as it is right now we would get an error. Why is this? Well, because we are importing a module from our “Todo.js” file we need to specify what this file exports. To do this we need to add the “export” keyword in front of what we want to make available from the “Todo.js” file. Thus, we need to change our code in our “Todo.js” file to the following…
import {react} from 'react'; export class Todo extends React.Component { render() { return(<div>I am a to do</div>) } };
Notice how we have added the “export” keyword in front of our class. Now there is something that can be imported from the “Todo.js” file. We will get into more complex combinations of what various files can export and import later on, but for now this simple example shows the basic setup of how it is done.
Now in our App.js file add the “render” method so we can confirm that everything is working…
import {react} from 'react'; import {Todo} from './Todo'; ReactDOM.render(<Todo />, document.getElementById('content'));
Let’s build our App.js file by running “webpack” by opening up a terminal window typing the following…
$ webpack
Doing the above will build the App.js file and place it in our “dist” folder. Now if we open up another terminal window and run our server with…
$ npm start
and we go to https://localhost:8080 in our browser, if all has gone well we should be able to see the text “I am a to do.”
Component Composition
For our application we will be rendering a list of “to do” items inside of our “to do” list. Thus, we will also need to create a component that represents our “to do” list. So create a “TodoList.js” file in the same directory as the others and add the following code…
import {react} from 'react'; import {Todo} from './Todo'; export class TodoList extends React.Component { render() { return(<div>To do list here...</div>) } };
“TodoList” is the component that will serve as our “root” container component for our React application. It is just returning some placeholder text for now, but we will be adding more complexity to it very soon. Because the “TodoList” top-level component for this particular application, it is this one that will be the one that we want to render in our App.js file (not the individual “Todo” components). So change the code in our App.js file to the following…
import {react} from 'react'; import {TodoList} from './TodoList'; ReactDOM.render(<TodoList />, document.getElementById('content'));
Notice now how we are now rendering the “TodoList” component now and not the “Todo” components.
Now let’s take a look at how we could add some “depth” to our components (i.e. nesting components within components). In this case we will be nesting individual “Todo” components inside of our “TodoList” component. So in our “TodoList.js” file we can update our code to the following…
import {react} from 'react'; import {Todo} from './Todo'; export class TodoList extends React.Component { render() { return (<Todo />); } };
It is as simple as that! You can include other components in what you return in your render method. This can include multiple components if you so desire…
import {react} from 'react'; import {Todo} from './Todo'; export class TodoList extends React.Component { render() { return ( <div> <Todo /> <Todo /> <Todo /> </div> ); } };
This example will render the text in our “Todo” component 3 times.
In a real-world application, what you render in any given React component will often include multiple components of many different types. This is what we refer to when we explain React components as being composable. They can be composed of multiple components of different types.
Our example is very plain right now. Let’s take a look and see if we can make things more dynamic by rendering out some variable data and adding some interactivity by wiring up some events (clicks, hovers, etc.)
Properties With this.props
We discussed the importance of this.props and this.state a bit earlier and we will expand upon this in the upcoming sections. To start let’s use some sample data. This data will again be an array of objects and will be somewhat similar to what we used earlier in our introduction to React. So update the App.js file to look like the following…
import {react} from 'react'; import {TodoList} from './TodoList'; let todos = [ { id: 1, title: "Eat Breakfast", summary: "Toast and scrambled eggs would be nice.", done: true }, { id: 2, title: "Walk Dog", summary: "Dress for wet weather.", done: false }, { id: 3, title: "Learn React", summary: "I am making great progress!", done: false } ]; ReactDOM.render(<TodoList data={todos} />, document.getElementById('content'));
Here we have an array of objects that we are going to pass in to our “TodoList” component. Inside of our component the data will be accessible by using this.props.data. The name “data” is just the name that I picked. You can choose any name that you want for your property attributes.
Continuing on, update the code in our TodoList.js file to the following…
import {react} from 'react'; import {Todo} from './Todo'; export class TodoList extends React.Component { render() { let items = this.props.data.map(function(item){ return (<Todo title={item.title} summary={item.summary} completed={item.done} />); }); return(<ul>{items}</ul>) } };
As we can see, we are accessing the data that is passed into our component with this.props.data. We iterate through the array and for each item, we pass the data in the item one level deeper into a “Todo” component. We create a collection of these components and return each one.
And then finally, let’s update our Todo.js file to the following…
import {react} from 'react'; export class Todo extends React.Component { render() { return( <li> <h2>{this.props.title}</h2> <p>{this.props.summary}</p> <input type="checkbox" checked={this.props.completed} /> </li> ) } };
So as we can see here, the title, the summary, and the flag on whether or not the item is marked as completed that we are passing into the component will be available with this.props.completed because we passed the done property in the object on each item into this slot.
Now if we build our files with $ webpack we can see the listing of our “to do” items. The ones that have the “done” property set to true have the checkbox checked.
Handling Events & State
One of the important parts that React applications handle for you is management of “state.” What is state? State is basically the current values that any given component holds that is often reflected in the way that the UI displays and represents its values. In our example above some of the items in our “to do” list hold a current state of being “completed” and some hold a current state of being “not completed.” State is the current collection of properties holding a set of values within a component. When the state updates, that is, when the value of one of these properties in a component changes, the component re-renders itself. We hinted at this piece of React briefly before and this one of React’s awesome features. Components re-render themselves when there is any change. We do not have to try to update things manually ourselves within the UI!
There are a number of different ways that a component’s state can change, but one of the more common ways is via events. Events are things such as mouse clicks and hovers that are usually instigated by a user but they can also be triggered in code as well. Wiring up events in React is similar to how it is done inline with JavaScript in HTML. You may have seen code like this before in vanilla JavaScript…
<script type="text/javascript"> function showMessage(){ alert("Hello world!"); } </script> <input type="button" id="messageButton" value="Submit" onclick="showMessage()" />
In the “onclick” attribute, we run the showMessage() function which will alert a message “Hello world!”. React takes a similar approach to this when it comes to hooking up events. Let’s see what this looks like. Update the code in “Todo.js” to the following…
import {react} from 'react'; export class Todo extends React.Component { constructor(){ super(...arguments); this.state = { completed: this.props.completed } } toggleCompleted(){ this.setState({completed: !this.state.completed}) } render() { return( <li> <h2>{this.props.title}</h2> <p>{this.props.summary}</p> <input type="checkbox" checked={this.state.completed} onChange={() => this.toggleCompleted()} /> </li> ) } };
You may have noticed the “…arguments” in the constructor. This is the spread operator that is a new feature in ES6 and in JSX. You also might notice our use of an arrow function that we discussed earlier in the “onChange” attribute. This is actually a necessity with regard to the scope of the component. If we did not use an arrow function here, the function in the attribute would create its own scope. Therefore we would have had to use “bind” and write something like onChange={this.toggleCompleted.bind(this)}. However, because arrow functions operate in the context of the parent scope, “bind” becomes unnecessary and the scope of the attribute operates under the scope of the component.
For the checkbox, we could attach and “onClick” event here if we wanted to and it would work fine, but instead of using the “onClick” event, we will use the “onChange” event because it is a bit more all-encompassing. In the future we will work with input textboxes, select boxes, and a number of other form elements. The “onChange” event will cover that a bit more comprehensively and we will be using it more regularly as we go along. There will be a time and a place for “onClick” specifically as well but in this case, onChange is a better fit.
If we build our code and ran this code as it is, we would get a warning message in the console saying…
Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `TodoList`. See https://fb.me/react-warning-keys for more information.
What is going on here? As we can see from the suggested page in the React docs there is a description of why this warning is appearing…
The situation gets more complicated when the children are shuffled around (as in search results) or if new components are added onto the front of the list (as in streams). In these cases where the identity and state of each child must be maintained across render passes, you can uniquely identify each child by assigning it a key… When React reconciles the keyed children, it will ensure that any child with key will be reordered (instead of clobbered) or destroyed (instead of reused).
So when dealing with events and state React requires a unique ID “key” to be attached for child components within a set. React uses this internally to allow for efficient reordering and identifying a specific item within the set. This is especially important when items are added to or removed from the set. So let’s update the code in our TodoList.js file…
import {react} from 'react'; import {Todo} from './Todo'; export class TodoList extends React.Component { render() { var items = this.props.data.map(function(item){ return (<Todo key={item.id} title={item.title} summary={item.summary} completed={item.done} />); }); return(<ul>{items}</ul>) } };
As we can see, we have passed in the item ID as the key property. That’s all we have to do! Once we do this and then rebuild our JavaScript this error message will go away. React is very helpful in giving us information with regard to how we need to change our code to set things up properly.
Now if we open our browser and go to our https://localhost:8080 site (run $npm start) we can see the items in our list rendered. The ones that have the “done” property set to true will have the checkbox checked. If we check/uncheck the checkboxes, the underlying data for the component underneath will be toggled as the “toggleCompleted” method will be running each time we do this. This brings us to the concept of state, something that is inexorably linked with events.
As we have mentioned earlier, state is the current collection of properties holding a set of values within a component. Collectively it is the status of the component at any given time and is subject to change at any time. This change will trigger React to do a “rerender” of the UI. In our example we are displaying the title and the summary with this.props.title and this.props.summary. In React, this.props is read-only and cannot be changed. Trying to set this.props.title = ‘Something Else’ will result in an error. Contrary to this.props, this.state is mutable. Because the “completed” property will change we will set an initial value for it in the constructor. Note that even though we cannot change anything on this.props we can still read the values in this.props to set an initial state. When certain events happen or certain functions execute, we can update the state of the component with this.setState and pass in an object containing all the properties we want to update. We will also do this for the title and summary properties later on when we get into writing our functions to edit our “to do” components. But for now we are just doing this with our “completed” flag.
That about does it for part 1. In part 2 we will work on filling out the application a bit more and adding in some validation. Until next time…
ECMAScript 6, Facebook, JavaScript, Node.js, React
0 Responses to To Do: Create Your First React Application – Part I