Authentication in React Applications, Part 1: Creating Components
• Updated:
React is a JavaScript library for building easy-to-maintain user interfaces. It was created by Facebook and Instagram engineers and made public in May 2013.
Why was React created? Apparently, engineers were unhappy with existing solutions. Libraries can be slow, do too little or too much. The code written using them can be hard to maintain. One of the main ideas behind React is that every DOM manipulation takes place in its own fast Virtual DOM and only after comparison with the old state of real DOM, decides to update changed elements. React is not bundled with a bunch of modules like an AJAX client. React doesn’t care how will you receive the data, it only cares about how to render components, how to process events and when to execute operations (before the rendering, or after it).
In this series of tutorials, we will implement an authentication layer in a small React application. The tutorial has been split into two parts:
‘Creating Components’. In this part, we will install dependencies for our project and create a basic application server and essential React components. We will add handlers for AJAX requests on a server side and validate them.
‘JSON Web Token’. In this part, we will focus on a user registration using an email address. For authentication, we will use JSON Web Token (JWT).
I’m not sure if the tutorial will be suitable for beginners in programming or JavaScript. But I hope it will be useful for readers who is pretty comfortable with JavaScript. And a command line interface and Node as well.
The source code for the project is available on Github.
Installing Dependencies
In this series of tutorials, we will use only essential packages to get running. So we will leave out CSS preprocessors and template engines in this tutorial. And seriously you don’t need another library just to perform AJAX requests.
At the time of writing, I used node 6.9.1 which is packed with npm 3.10.8.
Let's quick review dependencies:
express is a lightweight web application framework we will base our app on. It's probably the most popular solution in the Node environment
body-parser is an HTTP message body parser
react is a library for building user interfaces
react-dom is a package for React for the DOM rendering
react-router is a routing library for React-based applications
react-tap-event-plugin is a plugin for fixing tap delay for touch devices
validator is a library we will use for a user input validation
material-ui is a set of React components that follows Google's Material Design guidelines
webpack is a module bundler we will use for building our React application
babel-core, babel-loader, and babel-preset-es2015 are parts of Babel, that is useful for transforming a modern ES2015 code to a cross-browser solution
babel-preset-react is a Babel preset for all React plugins
nodemon is a wrapper for Node that monitor changes in an application code and automatically restart the server
In your project directory initialize a Node project by typing:
You can leave all options as default or customize as you need.
Now let’s install the packages:
After installing all packages, my package.json file has looked almost like this:
package.json
Notice, I added two lines to the scripts section:
The first command is for starting the application in the strict mode. The second one is for bundling client-side scripts by Webpack.
Project Directory Structure
At the end of this part of tutorial, the application will have the next directory structure:
The first thing we need to do is create an entry file for the application. Here is the index.js file:
index.js
Notice we haven’t specified the route for root path. Express will look for an index.html file located in the server/static directory. For this file we will use a simple HTML layout like below:
server/static/index.html
And the stylesheet file. Many of the rules we will use later.
server/static/css/style.css
Let’s build our first React app. Create a file client/src/app.jsx:
client/src/app.jsx
You’re probably confused by the HTML tag passed as the function argument. Well, it’s not HTML, it’s JSX, a XML-like syntax extension to ECMAScript. JSX is not supported by any browsers, we have to transform it to a plain JavaScript. For this task, we will use a Babel plugin.
In our case, the string with JSX will be transformed to this:
The second argument, which is now simply null, is for passing HTML tag attributes. We will see a usage of them later. It’s not necessarily to use JSX though it’s a commonly recommended way of writing React code.
To bundle React from npm and transform the JSX template to a plain script, which we will serve to a browser, we will use Webpack with the Babel loader. Webpack is not the only option to do the same task. It’s also possible to use Browserify but it’s out of the scope of this tutorial.
Let’s create a config file for Webpack and review it. Save the config in webpack.config.js in the root directory of the project.
webpack.config.js
In the config, we have set the loader plugins that will only apply to the files matching the regular expression. The expression is set in the test property of the passed object in the given directory (the property include). For these files we will use Babel with presets: ‘react’ and ‘es2015’. The preset ‘es2015’ will set Babel to compile the ES2015 code to ES5 in order to get to the application a cross-browser support.
Let’s see our simple app in action. In your terminal open two windows (or tabs) and go to the project root directory. In the first window, run:
And in the second window, run:
Or if you installed Webpack globally, you may bundle scripts by typing webpack in the command line in the root directory of the project.
Now in your browser, go to http://127.0.0.1:3000 (or http://localhost:3000). If everything is okay you should see:
Creating Presentational Components
Before we get started we should understand what React components are. Components are the individual building blocks of UI. For example, an input field may be one of the components of the form. The whole form is also a component of a contact page on a site.
A very interesting pattern to consider while creating components is dividing them into two categories. They called Container and Presentational components. Presentational components focus on how things look and Container components focus on how things work.
Let’s create and review our first presentational component for the home page:
client/src/components/HomePage.jsx
Since JSX is JavaScript, the class keyword already reserved, so instead of it, we have to use the className attribute. Another example is the for attribute, instead of it, we write htmlFor.
Our presentational component uses Material UI’s components like Card and CardTitle. You may think of Material UI’s components like of elements with predefined behavior and CSS styles. Our component renders the simple text as a title and subtitle.
An important notice: a component should have one root element (in our case this element is the Card component). Writing multiple components without a single parent is a syntax error.
That’s it, we have defined the simple presentational component. Usually, it’s just a function that returns the markup. If we would want to render this component right now, we would need to import it, and then pass the component to the ReactDom’s render method like this:
Now we will create a much more complex presentational component for the sign-up form:
client/src/components/SignUpForm.jsx
Let’s review the component step-by-step.
Notice the extracted variables from the object passed as a function argument. It’s how we get data to show in a presentational component. We have four variables, onSubmit and onChange are event handler functions, errors and users are objects containing data. How can we pass an object to extract variables from? Each element can be passed as a property (in React properties simply called props):
In the form tag, you can see the usage of the function stored in the onSubmit variable for the form submission event.
Since if conditions don’t work inside of JSX, we use statements like this:
The element will be shown only if the property errors.summary contains something or equals true.
Components like TextField, RaisedButton, CardText are parts of the Material UI library. These components are not only nice-looking elements but also have useful features. For example, the TextField component has a prop errorText` for showing an individual error tip.
For building links in templates we use the <Link> component that will render an a tag with a proper href attribute.
An important concept in React is type checking of props with PropTypes. With PropTypes we set rules for props of a component: what data type expected to be passed or whether it is required or not. Setting these rules is helpful and intended to prevent making errors while developing a React application:
Let’s create another (almost identical to the sign-up form) component for the login form:
client/src/components/LoginForm.jsx
And the last presentational component that will work as a wrapper for the whole application:
client/src/components/Base.jsx
The children object will be passed as a prop by a router that we will configure later.
Creating Container Components
Now we will look at creating container components in action. Containers components do the hard work: update values for showing in presentational components, validate user’s input. In our case, in containers, we also will perform AJAX requests.
Our first container component will be a component that will process the previously created the sign-up form:
client/src/containers/SignUpPage.jsx
As you see, container components are created by extending a class from the core React.Component class.
In the constructor method, we have set the default component state. The state is a set of values only available within a component. The state initialization with default values should take place before a component is rendered.
Why do we need so-called state if we got a regular class with fields? Sure we can set values to the this-reference and then get them in any other method of the class.
At some point, we may need to re-render a component. For example, after receiving an updated list of products we need to make React re-render the component with updated values in the list. It’s the state for, we set initial values, then we update the state with the setState method and React will re-render a component.
Look at the statements at the bottom of the constructor:
It’s for passing the this-context, so we will have an access to class members from event handlers defined as methods.
The first event handler defined in the method called changeUser will change the component state by taking the name attribute of an input element as a key. A value for this key will be taken from a user’s input.
In the second event handler processForm, which would happen when a user submits the form, all we do at this moment is outputting current state values to the browser console.
The last method render is required for every component created as a class. In this method, we render the presentational component SignUpForm with the passed event handlers and state values as props.
The second container component will process the login form. The container at this point is almost the same as the SignUpPage container:
client/src/containers/LoginPage.jsx
Now we need to set a routing for the application:
client/src/routes.js
The routes config is a JavaScript object containing the main component, which we will use as a wrapper for the application, and an array of child routes.
As you see we have set the HomePage component as the index route of our application, the SignUpPage component for the /signup path and the LoginPage component for the /login path.
The next step will be an updating the client-side entry file. We need to include our router config and apply Material UI’s theme manager:
client/src/app.jsx
If your instances of Webpack (npm run bundle) and Nodemon (npm start) are still working, you should see the welcome page by entering http://localhost:3000 in a browser.
Go to the sign-up form. We have the event handler for the submit button, try to fill the fields and check an output in browser’s console.
Check the login form:
Server-Side Routes
For the sake of shortness, we won’t implement the client-side validation as it’s not essential (yet, it’s very useful for UX) and will focus on the server-side one. The first thing we need to do is to be able to read a POST-data, so let’s configure our application server.
Change the index.js file to this:
index.js
We added the loading of the body-parser package and configured the application to use it. We also included routes.
Let’s create these routes for processing the form data, which we will send via AJAX requests. To include a separate file with the route rules we’ve passed the middleware app.use('/auth', authRoutes).
Save the routes:
server/routes/auth.js
In the file, we’ve set the two POST-method routes, for /auth/signup and for /auth/login. Also, we added the validation functions with basic rules to check if passed data contains a valid email address and to ensure if a password contains at least 8 characters. We should get an HTTP response with the status code 400 (bad request) and a JSON object containing error messages if validation doesn’t pass. If everything is okay and validation passes, we will get an HTTP response with the status code 200 (success).
It’s the time to add AJAX requests to our components. Change the SignUpPage container component:
client/src/containers/SignUpPage.jsx
We added an AJAX request to the processForm method. In the method, we change the component state values depending on an HTTP response status code.
Similar to the sign-up page container we will change the login form container:
client/src/containers/LoginPage.jsx
Let’s see the components in action. In a browser, try to submit sign-up form the form with the empty fields or with a very short password.
If the form is valid you should see the phrase ‘The form is valid’ in console:
Check if the login form works properly too.
Conclusion
This part of the tutorial covered essentials concepts of JSX syntax, React components, state and props values. It’s also showed how to use tools like Webpack.
In the next part, we will continue to build the application and implement the authentication layer using an email address.