#100DaysOfCode Day 37: Single-Page Application in React.js

Richard Russell
Cold Brew Code
Published in
7 min readJul 22, 2020

Hello, World!

Today, I will be going over a new project: creating Single-Page Applications in React.js and React Router. Single-Page Applications are different from the traditional multiple-page apps, where each specific page will have its own respective file associated with it. With Single-Page Applications, you can navigate over several different pages without having to load the page as an entirely new entity. In short, a single-page application dynamically rewrites the current page with new data from the web server, instead of the default method of loading entire new pages on its own. The goal is a faster transition that makes the website feel more like a native application.

Single-Page Applications (we will refer to it as SPAs) have actually been around for years, but they have not yet become widely used across the public internet. In the early stages, SPAs were adopted to build the private dashboards of SaaS (Software-as-a-Service) applications. This progression can then be seen in other online web applications, such as e-school platforms (Coursicle, Moodle, OpenLearn) or online social media applications (Facebook, Twitter).

When making a Single-Page Application, things can get challenging. For one, the developer needs to make sure that Single-Page Applications behave according to how users would expect them to. This would mean that Singe-Page Applications would have to:

  1. Reflect the content of the page based on the URL displayed in the address bar
  2. Use the back and forwards button
  3. Navigate to a particular content using the appropriate URL

With multiple-page applications, these things come included in the box. However, when it comes to Single-Page Applications, you have to make several adjustments to ensure that the user still gets the same user-experience as a traditional multiple-page application. This means that you need to ensure that navigating within the content of the Single-Page Application also adjusts the URL accordingly, that your browser’s history is properly synchronized with each navigation to allow users to use the back and forward buttons, and that the Single-Page Application will show the appropriate content according to the specific URL.

To deal with this, we can use routing. Routing is where you map URLs to destinations that aren’t physical pages, such as the individual views in the Single-Page Application. One such JavaScript library that will help us with routing is React Router. React Router provides routing capabilities to Single-Page Applications built with React.

Initializations

The first thing we need to do is initialize our React application. To do this, open your Terminal application and run the following command:

npx create-react-app react_spa

You don’t have to name your program as react_spa; give it any name you want.

Running the command above will create a new project folder called react_spa. Open this folder using cd react_spa and then run the following command:

npm install react-router-dom`

The command above installs the react-router-dom package.

Now that you have initialized your react application, you will have to clean up and delete several contents of the app. Inside react_spa, delete every content of inside public and src folders. Once you have done this, create an index.html file inside the public folder with the following code:

<!DOCTYPE HTML>
<html lang='en'>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>React Router Example</title>
</head>
<body>
<div id="root"></div>
</body>
</html>

Next, we will create our JavaScript entry point. Inside your src folder, create a file called index.js and add the following code:

import React from 'react';
import ReactDOM from 'react-dom';
import Main from './Main';
ReactDOM.render(<Main/>, document.getElementById("root"));

As you can see in the ReactDOM.render() function, we are calling a Main component. However, this component does not exist yet. The Main component will be the starting point of our Single-Page Application.

Building the Single-Page Application

To build the SPA, we will need to create the main parent component first. Next, we will create the individual “pages” of our app to separate the component that will then be fed back into the parent component. React Router will assist in showing and hiding the pages that needed to be shown or hid.

Parent Component — The Initial Frame

When building a SPA, there will always be a part of the page that remains static — the header, footer, navigation bar, or even an empty area for the content. This is called the static part, also referred to as the app frame. In our case, our app frame will be the navigation header and an empty area for the content to load.

Inside our src folder, create a new file called Main.js with the following code:

import React, { Component } from "react";class Main extends Component {
render(){
return(
<div>
<h1>Simple SPA</h1>
<ul className="header">
<li><a href="/">Home</a></li>
<li><a href="/stuff">Stuff</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
<div className="content">
</div>
</div>
);
}
}
export default Main;

Afterward, you can begin your React app by running npm start, you will then see an unfinished version like above. After creating the app frame, we will create individual content pages.

Creating the Content Pages

We will be making three different content pages. This content will be a simple component that prints our some JSX. First, create Home.js in the src directory:

import React, { Component } from 'react';class Home extends Component {
render(){
return (
<div>
<h2>Hello</h2>
<p>This is the Hello Page! You can write anything you want in here</p>
</div>
);
}
}
export default Home;

Next, create stuff.js:

import React, { Component } from 'react';class Stuff extends Component {
render(){
return(
<div>
<h2>Stuff</h2>
<p>You can write your own stuff in here</p>
</div>
);
}
}
export default Stuff;

Lastly, create Contact.js:

import React, { Component } from 'react';class Contact extends Component {
render(){
return(
<div>
<h2>CONTACT</h2>
<p>Write down your email or something in here</p>
</div>
);
}
}
export default Contact

Overall, our individual pages are basically made out of JSX code that prints out our desired content. Now, we will have to edit our Main.js file again and add our React Router.

Using React Router

We already have our app frame in our Main component. We also have our content pages in the Home, Stuff, and Contact component. What we need to do now is tie them together to create our Single Page Application. This is where React Router comes in. To start using it, go back to Main.js and add the following imports:

import {Route, NavLink, HashRouter} from 'react-router-dom';
import Home from './Home';
import Stuff from './Stuff';
import Contact from './Contact';

Next, we are going to change the content of our render to add React Router functionalities.

class Main extends Component {
render(){
return(
<HashRouter>
<div>
<h1>Simple PUA</h1>
<ul className="header">
<li><NavLink to="/">Home</NavLink></li>
<li><NavLink to="/stuff">Stuff</NavLink></li>
<li><NavLink to="/contact">Contact</NavLink></li>
</ul>
<div className="content">
<Route path="/" component={Home}/>
<Route path="/stuff" component={Stuff}/>
<Route path="/contact" component={Contact}/>
</div>
</div>
</HashRouter>
);
}
}

Now, the way React Router work is by defining a routing region. Inside this region, you will need to handle these two things:

  1. Your navigation links
  2. The container to load your content info

The first thing we need to do is define our routing region inside our Main component’s render method. We do this by adding <HashRouter> tags, which provides the foundation for navigation and browser history handling. Next, we are going to define our navigation links. To do this, simply replace the <a> anchor tags with a more specialized <NavLink> component.

For each link, the respective URL value (defined by the to prop) acts as an identifier to ensure that the right content gets loaded. We can then match the URL with the content using the Route component, which contains a path prop. The value you specify for the path determines when this route is going to be active. When a route is active, the component specified by the component prop will get rendered.

For example, when we click on the Stuff link, which has the /stuff path set by NavLink, the route with path value of /stuff also becomes active. This means that the contents of our Stuff component gets rendered.

Refining the Details

Before finishing our application, let us refine several important details! The first one being, if you try to run the app using npm start or simply refresh the browser (as React automatically reloads based on any change towards the code), you will see that the Home page gets rendered regardless of the current page. This is because the path set to Home is /, which is also included in the path of stuff ( /stuff) and contact ( /contact). This can be fixed by using the exact prop to the Route tag:

<div className="content">
<Route exact path="/" component={Home}/>
<Route exact path="/stuff" component={Stuff}/>
<Route exact path="/contact" component={Contact}/>
</div>

adding the exact prop means that the route needs to be exactly / in order for Home component to load.

Now, let us also add some CSS to make this page better. Create an index.css file inside your src folder and write this code:

body{
background-color: #FFCC00;
padding: 20px;
margin: 0;
}
h1, h2, p, ul, li{
font-family: sans-serif;
}
ul.header li{
display: inline;
list-style-type: none;
margin: 0;
}
ul.header {
background-color: #111;
padding: 0;
}
ul.header li a{
color: #FFF;
font-weight: bold;
text-decoration: none;
padding: 20px;
display: inline-block;
}
.content{
background-color: #FFF;
padding: 20px;
}
.content h2{
padding: 0;
margin: 0;
}
.content li {
margin-bottom: 10px;
}
.active{
background-color: #0099FF; /*Highlights current page*/

Next, we need to import the index.css file to the top of index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import Main from './Main';
import './index.css';
ReactDOM.render(<Main/>, document.getElementById("root"));

Lastly, we are going to add another exact prop, this time to the NavLink tag:

<li><NavLink exact to="/">Home</NavLink></li>
<li><NavLink to="/stuff">Stuff</NavLink></li>
<li>NavLink to="/contact">Contact</NavLink></li>

Once you’re done, you can see the results of your application!

Conclusion

Single Page Applications is another field in web development that I have just found about. It comes to show that the world of web development is really huge and that even then there are still a lot of specific functionalities inside of it. For now, it seems worthwhile to dive around the different technicalities there is to know about web development.

--

--

Richard Russell
Cold Brew Code

i like to write about code. i also like cold brew coffee.