React is a Javascript library that helps break down complex UI into simple and reusable components that can be composed together. I will show you how to build a react app from scratch, using the Stormpath React SDK to add sign up, login and view profile features.
Let's get started!
You'll first need to create a Stormpath account and application, which you can do here: https://api.stormpath.com/register
Stages we are going to cover:-
- Install the React + Express.js Application Stack
- Set up the React + Express.js Project
- Master Page
- Index Page
- Login Page
- Registration Page
- Profile Page
- Home Route
- Logout
- User State in Components
- Import Components
- Run The project
- Wrapping Up
Install the React + Express.js Application Stack
In this tutorial, we will use ES6 and JSX to write as little code as possible as well as Stormpath React SDK for user features.
Here's a break down of what we will use:-
- React - Allows us to compose simple yet powerful UIs.
- ReactRouter - Organizes the URL navigation in our React application.
- ES6 - The next version of JavaScript. Allows us to write real JavaScript classes.
- JSX - Allows us to place HTML in JavaScript without concatenating strings.
- Stormpath - Allows us to store and authenticate users without having to create our own backend for it.
- Stormpath React SDK - Integrates Stormpath into our React application with very little effort.
- Express - Allows us to serve our HTML and JavaScript files. Express Stormpath - Allows us to serve Stormpath's API through Express.
- Webpack - Allows us to pack all of our JavaScript files into one bundle.
- Babel - Allows us to transpile our ES6 and JSX into ES5.
- Bootstrap - Because we want things to be pretty.
Set up the React + Express.js Project
Create a directory where your project will sit
$ mkdir my-react-app
$ cd my-react-app
$ npm init --yes
Install Express and the Stormpath module for Express:
$ npm install --save express express-stormpath body-paser
Next, we will create a server to host our application. Create a new file server.js
and paste the code below:
const express = require('express');
const stormpath = require('express-stormpath');
const app = express();
app.use(stormpath.init(app, {
web: {
produces: ['application/json']
}
}));
app.on('stormpath.ready', function(){
app.listen(3000, 'localhost', function(err){
if(err){
return console.error(err)
}
console.log('Listening at http://localhost:3000')
});
});
Next, we can go ahead and hook this up to our Stormpath Application by creating a new file stormpath.yml
with the following code in it. Of course, you have to replace the values with your own.
client:
apikey:
id: YOUR_API_KEY_ID
secret: YOUR_API_KEY_SECRET
application:
href: https://api.stormpath.com/v1/applications/XXXX <-- YOUR APP HREF
Try the server by running $ node server.js
. If everything is set up correctly, you'll see:-
Listening at http://localhost:3000
Great, you can give yourself a thumbs up for that. You've earned yourself a badge for successfully configuring your server to communicate with Stormpath and expose a REST API for your React.
Configure Webpack
Moving on swiftly, terminate the server so that we can install the Webpack package. As we mentioned earlier, Webpack is going to package all of our client-side scripts. We will need this organization soon!
$ npm install --save webpack
$ npm install --save-dev webpack-dev-middleware
We will configure Webpack by creating a new file named webpack.config.js
by inserting the code below:
const path = require('path');
const path = require('webpack');
module.exports = {
entry: [
'./src/app'
],
devtool: 'eval-source-map',
output: {
path: __dirname,
filename: 'app.js',
publicPath: '/js/'
},
module: {
loaders: []
}
};
So let's dissect this code:-
What this code does, is that it will look in our /src/
directory (don't worry, we will create that) and package all of the scripts and their dependencies under that directory as one module. Then use the file /src/app.js
and its exports as the export of that module. Then finally when it has generated that module package, it will serve that through Express
under the /js/app.js
endpoint.
In order for Express to serve Webpack files, we have to add a few lines on top of the scripts in server.js
file:
const webpack = require('webpack');
const config = require('./webpack.config');
Then immediately after the line const app = express();
add:
const compiler = webpack(config);
app.use(require('webpack-dev-middleware')(compiler, {
noInfo: true,
publicPath: config.output.publicPath
}));
Again, this will allow Webpack to intercept requests and serve our packaged /js/app.js
file.
Configuring Babel
Since we will be using ES6 and JSX, we need to transpile these files into ES5 (for backward compatibility with non-modern browsers). Babel does this. It takes ES6/JSX files as input, and convert them to ES5.
So, as usual, we are going to install Babel package
$ npm install --save babel-core babel-runtime babel-loader babel-plugin-react-transform \
babel-preset-es2015 babel-preset-react babel-preset-stage-0
Next, just as we did with Webpack, we are going to configure babel by creating a new file .babelrc
and adding this code:-
{
"presets": ["stage-0", "es2015", "react"]
}
Finally, we need to edit webpack.config.js
in order to allow Babel to work with our Webpack. We will add an entry to the module.loaders
array:
module: {
loaders: [{
test: /<.js$/,
loaders: ['babel'],
include: path.join(__dirname, 'src')
}]
}
Index.html and Bootstrap
Before deep-diving into React and getting ourselves wet, we'll set up the entry page for our app. This page will instruct the browser on what it must load before we initialize React and our application.
Start by creating a new directory build
, inside it, create a file index.html
. Our server will serve all our static files from this folder.
$ mkdir build
$ cd build
$ touch index.html
Within index.html
, insert this:
<!doctype html>
<!--[if lt IE 7]><html class="no-js lt-ie9 lt-ie8 lt-ie7"><![endif]-->
<!--[if IE 7]><html class="no-js lt-ie9 lt-ie8"><![endif]-->
<!--[if IE 8]><html class="no-js lt-ie9"><![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js"><!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<base href="/">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="/css/bootstrap.min.css" />
</head>
<body>
<div id="app-container"></div>
<script src="/js/app.js"></script>
</body>
</html>
If you are using Visual Studio Code as your editor, you can install the HTML-5 Boilerplate
extension to easily generate the HTML script.
Moving on, in the build
folder, create a new directory css
and download bootstrap files to it.
$ mkdir css
$ cd css
$ curl -O https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css
$ cd ../.. # return to /my-react-app
In order for our browser to access these files, we need to configure them so that they are served through Express. Open up server.js
and at the top of the file add:
const path = require('path');
Under the line app.use(stormpath.init(app, ...));
add:
app.get('/css/bootstrap.min.css', function(req, res) {
res.sendFile(path.join(__dirname, 'build/css/bootstrap.min.css'));
})
app.get('*', function(req,res) {
res.sendFile(path.join(__dirname, 'build/index.html'));
});
A Little Bit on How React Works
We now have a skeleton for our app done, next we will focus on building our React app. But before that, let's try to understand React.
Components
In React, everything is built upon components. Think of a component as an element on the DOM e.g. Navigation Bar, Header, Login Form ... etc. A component is basically something that renders a DOM node. A simple React component looks like this:-
class FirstComponent extends React.Component {
render(){
return <div>First Component</div>
}
}
To render this component to the page, you need to import react and then call it:
ReactDOM.render(
<FirstComponent />,
document.getElementById('first-component')
);
And React would render the component to that element.
Of course, there are more things to a React component, such as state , componentWllMount, componentWillUnmount etc. To give you a glimpse of this, let's create a simple React Component counter that starts counting immediately when added to the DOM and stops when removed.
class Counter extends React.Component {
state = {
current: 0
}
constructor(){
super();
this.intervalId = null;
}
updateCounter(){
this.setState({current: this.state.current + 1})
}
componentWillMount(){
this.setState({ counter: this.props.from || 0 });
this.intervalId =
setInterval(this.updateCounter.bind(this), 1000);
}
componentWillUnmount(){
clearInterval(this.intervalId);
}
render(){
return <span>{ this.state.current }</span>
}
}
So now let's try to understand this. The methods componentWillMount()
and componentWillUnmount()
are life-cycle methods that will be executed at various points of a component's life-cycle (in this case, mount and unmount). The methods are usually used for setting up and tearing down a component and is necessary to use because React will error if you try to set the state of a component when it hasn't been mounted yet.
The member this.props
is a collection of all the properties (inputs) passed to a component. Properties of a component can be set like this:
<Counter from="50" />
<Counter from={ myVariable } />
JSX Variables
Variables can easily be interpolated into your JSX DOM using { nameOfVariable }, e.g. like this:
render(){
let myVariable = 123;
return <span>{ myVariable }</span>
}
JSX and Reserved JavaScript Identifiers
Since JSX is JavaScript, there are some caveats that you need to know when working with React. i.e when setting properties of a React DOM component you cannot use neither for
nor class
since those are considered reserved JavaScript identifiers. To get around this problem, React has come with htmlFor
and className
that you should use instead.
To illustrate the issue, this won't work:
<label for="my-input" class="my-label">My Input</label>
But this will:
<label htmlFor="my-input" className="my-label">My Input</label>
Virtual DOM
Instead of working directly against the DOM, in React all components are kept in their own virtual DOM. You can think of the virtual DOM as a DOM implementation in JavaScript (because it actually is). This virtual DOM is then mapped to a real DOM element. So when you render your React component, React will look at the DOM output from the component, compare it to its representation in the virtual DOM, and then generate a patch for the real DOM.
What this means is that you never have to think of manually manipulating DOM elements again. All you have to do is tell React how you want your component to look like, and it will take care of transforming the DOM the ways necessary (with minimal effort).
Installing React Dependencies
Now that we are acquainted with React, we'll kick things off by installing some React dependencies:
$ npm install --save react react-dom react-router react-stormpath react-document-title history
Before we start coding, we need a place to put our React files, so create a new directory named src
, and then use that as your working directory.
$ mkdir src
$ cd src
Now, let's start with the entry point of our app. This will be the place where we will set up our React application and its routing. So create a new file named app.js
and enter this code:
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, IndexRoute, Route, browserHistory } from 'react-router';
ReactDOM.render(
<Router history={browserHistory}>
</Router>,
document.getElementById('app-container')
);
So now we have a foundation for our application. Let's go ahead and import the Stormpath SDK and some things we'll need in it. At the top of your app.js file, add the import statement:
import ReactStormpath, { Router, HomeRoute, LoginRoute, AuthenticatedRoute } from 'react-stormpath';
As you can see in app.js
there's now two conflicting Router
imports. Since ReactStormpath.Router
extends from ReactRouter.Router
we won't be needing that anymore. So go ahead and remove the Router
import from react-router
. Important: Leave the other ReactRouter imports, we'll be needing those later.
Now, we'll initialize the Stormpath SDK. Add the following line right above ReactDOM.render()
.
ReactStormpath.init()
That was easy! We're now ready to start building our pages on Part Two of this tutorial.
Top comments (3)
This is a really great guide for Stormpath and React, but Stormpath no longer exists as a company as it has been purchased by Okta. In fact if you go to the Stormpath site, it indicates "Stormpath has joined forces with Okta. The Stormpath API shut down on August 17, 2017". The stormpath NPM module as well as stormpath-react haven't been published/updated in 3+ years. Iād really recommend reviewing the Okta documentation instead. This is just a warning and not a reflection of the quality of this guide/post.
Thanks Alexander,
I appreciate. Let me review
Nice overview of starting a new React app!
I hadn't seen Stormpath before - thanks for pointing that out :)