Journey into React Part 3: Navigating Between Webpages with React Router

Start your react journey today, with part 1.

Hello and welcome back for part 3 of our journey into React. By now, you've set up your windows based work environment, and have created your first hello world app. If you've missed these, I'd highly recommend going back and reviewing them: part 1 is here, and part 2 is here.

Today we are going to be expanding on this hello world app to start to fit the needs of the end application we'll be building. In review, we are working on an address book application that is going to store our contacts in a Mongo database. Our application will support multiple accounts, will authenticate securely, and will provide us with the ability to add, erase, call, or email our contacts all from within the browser. So going forward we are going to start pushing our application in that direction.

Our goal today will be really digging into our React app by implementing react-router, the dependency that will allow us to control what "page" the user sees. There is a lot that goes in to making applications so I want us to get a decent working knowledge of one thing before moving on to the next. One of the biggest problems I ran into when learning how to make my first application was information overload. So, this tutorial and the next one will be focusing on the client side of our program.

You can view the completed version of part three at my GitHub repo.

Why we need React-Router

Unlike a traditional website that serves different files to it's clients (like, the home page, the login page, and the about page), React is delivering a single html file to the client. This file contains all of our applications code and depends on something called a router to "simulate" the appearance of different web pages. Whenever a user clicks a link that navigates them around our app, it's only a command telling the application what component to display on the users screen. We can use react-router to simulate different urls, and make the application feel more like a traditional website.

As that sinks in, let's get started implementing react-router into our own application.


Creating our route controller

First things first we're going to need to implement a new dependency:

$ npm install react-router --save

Now, we're going to create a new file in our src directory titled routes.js, which within we'll start creating our router.

import React from 'react';  
import { Route, IndexRoute } from 'react-router';  
import App from './components/app';

export default (  
  <Route path='/' component={App}>
    <IndexRoute component={App} />
  </Route>
);

The top part should be familiar by now; we've imported our React dependency, and our App component, as well as the functions Route and IndexRoute from our newly installed react-router package. The new part there is the export default function where we've created our <Route /> We passed this route the route path (path='/') and set the component to "App". We've also added an IndexRoute which (for the time being) is also pointed to the "App" component.

Here is where most of the routing magic happens. By defining the path parameter of our route, we are telling React to display the "App" component when the url is equal to this path. We'll see how this is used a bit more down below, but first lets patch in our router so that we can use it.

Including the Router into our App

Let's jump on over to the index.js file we have in our src directory. You'll recall that we had imported the "App" component and plugged it into the ReactDOM.render() function. We're going to instead implement our router so that we are delivery all of our pages to the client.

import React from 'react';  
import ReactDom from 'react-dom';  
import { Router, browserHistory } from 'react-router';  
import routes from './routes';

ReactDOM.render(<Router history={browserHistory} routes={routes} />, document.querySelector('#app'));  

Notice we imported Router and a new function browserHistory here, as well as including our routes from the routes.js we just created. In our render function we've added the Router with the first parameter which will remember our clients browsing history across our site, and we're defining the routes as our routes.js function. And that's about it, go ahead and run your application again to make sure it's still working, and meet me in the next section.

Adding a few new components

Let's take another look forward at what our application is going to need right away. We'll need a dashboard where we can view our contacts, and of course a login page to get in to the dashboard. We'll also need a navigation bar to switch between pages. Let's just make some simple components exactly like our first one, and change the contents so we can tell them apart.

src/components/dashboard.js
import React, { Component } from "react";

export default class Dashboard extends Component {  
  render() {
    return (
      <div>
        This is the dashboard
      </div>
    );
  }
}
src/components/login.js
import React, { Component } from "react";

export default class Login extends Component {  
  render() {
    return (
      <div>
        Login Form will go here
      </div>
    );
  }
}

And now let's make a very simple navigation list so we can move between them (once we connect everything together of course). We're going to import a new function here from react-router as well that we'll use much like standard <a /> tags in html.

import React, { Component } from "react";  
import { Link } from 'react-router';

export default class Navigation extends Component {  
  render() {
    return (
      <div>
        <ul>
          <li><Link to="dashboard">Dashboard</Link></li>
          <li><Link to="login">Login</Link></li>
        </ul>
      </div>
    );
  }
}

Now that we've created two new pages for our website, let's get it imported into our router.

Implementing new pages into the router

So we've created some new components and we want them to act as pages for our website. Let's jump back over to our routes.js file and add them like this:

import DashBoard from './components/dashboard';  
import Login from './components/login';

export default (  
  <Route path='/' component={App}>
    <IndexRoute component={DashBoard} />
    <Route path='dashboard' component={DashBoard} />
    <Route path='login' component={Login} />
  </Route>
);

You'll recognize the IndexRoute, but notice we changed the target component to the DashBoard. We've also added two new paths that point to the new components we just made. Make sure the path here is equal to the link to={} destination in our navigation component as well.

Now, we need to bring this all together somehow. In our app.js file we previously had the words "hello world" within our rendered div. We're going to swap that out for a property that will represent the entirety of our website.

import Navigation from './navigation';

export default class App extends Component {  
  render() {
    return (
      <div>
        <Navigation />
        {this.props.children}
      </div>
    );
  }
}

You can think of the app.js file as the entirety of our application. Within the rendered div of our "app" component everything our clients see will be displayed. So by importing the navigation.js file we are telling our application to display the navigation bar at the top of the div, and underneath it all of the other components {this.props.children}. The router than controls which components are displayed.

We can now load up our application again and and we'll see our ugly ul, and the dashboard component. If you click the links you'll notice the url changes and it should display the appropriate component.

Our current project screenshot

It doesn't look too pretty, but we'll fix that next time. For now, sit back and enjoy your work - you've just created your own multi-page React app using react-router. You've already experienced the power behind the component based style of React by changing and improving your app.js file to accommodate your new router, and making small changes to your index.js file that dramatically impacted the overall project. It's a big step - but are you ready to take some more in our Journey into React?

Until next time, happy coding!

David Meents

React.js developer, web designer, and business owner.

Subscribe to David Meents

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!
comments powered by Disqus