Adding react-router-dom is a piece of cake by now. Just take yarn or npm and add it to your project. Let's get started with our boilerplate code. Copy all of the starter files. We already added react-router-dom to our app in Chapter 3, Routing, and Chapter 4, The Concept of Immutability. If your app does not have react-router-dom, you can add it as follows:
yarn add react-router-dom --exact
OR
npm install react-router-dom
In our health application, we will have the following pages:
Page Description |
Page Component |
Page Routes |
Home page |
HomePage |
/ |
About page |
AboutPage |
/about |
Contact page |
ContactPage |
/contact |
Register page |
RegisterPage |
/register |
Login page |
LoginPage |
/login |
Forget password |
ForgetPassword |
/forget-password |
Reset password |
ResetPassword |
/reset-password |
Dashboard page |
Dashboard |
/admin/dashboard |
List of users |
UsersList |
/admin/users |
View single user |
UserDetail |
/admin/users/:userID |
Edit single user |
EditUser |
/admin/users/:userID/edit |
The react-router-dom package includes a <BrowserRouter> component. The <BrowserRouter> component is an implementation of the router interface that makes use of HTML5's history API, in order to keep the UI in sync with the URL path. As mentioned on the documentation site, we can use <BrowserRouter> to implement simple routings, as follows:
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
Inside of our App container, we can implement the logic for other routes. For example, to get to the about page and contact page, let's implement two routes, /about and /contact. Inside of App/index.js, include two routes, as follows:
import React from "react";
import { Switch, Route } from "react-router-dom";
import HomePage from "containers/HomePage/Loadable";
import NotFoundPage from "containers/NotFoundPage/Loadable";
import AboutPage from "containers/AboutPage/Loadable";
import ContactPage from "containers/ContactPage/Loadable";
import GlobalStyle from "../../global-styles";
export default function App() {
return (
<div>
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/about" component={AboutPage} />
<Route exact path="/contact" component={ContactPage} />
<Route component={NotFoundPage} />
</Switch>
<GlobalStyle />
</div>
);
}
That was not very difficult, was it? Now, we can update our logic to include all of the routes, as given in Table 6.1. Once we include all of the routes, as specified in the table, our route files should look like following:
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/about" component={AboutPage} />
<Route exact path="/contact" component={ContactPage} />
<Route exact path="/login" component={Login} />
<Route exact path="/forget-password" component={ForgetPassword} />
<Route exact path="/reset-password" component={ResetPassword} />
<Route exact path="/admin/dashboard" component={Dashboard} />
<Route exact path="/admin/users" component={UsersList} />
<Route exact path="/admin/users/:userID" component={UserDetail} />
<Route exact path="/admin/users/:userID/edit" component={UserEdit}/>
<Route component={NotFoundPage} />
</Switch>
Now, it is just a matter of defining each individual component. We have created a simple React application with multiple pages. In Chapter 5, React with Redux, we will create a list of these views, and it can be connected easily.
As stated in the Redux documentation, Redux is the single source of truth of the data. In the same manner, the React router is the single source of truth for any application URLs. This works great in most cases, unless we require time traveling and rewinding actions that trigger a URL change. In such cases, we need a Redux binding for React Router. There are other, third-party libraries that can help us in this context. In our application, we are going to use ConnectedReactRouter, which provides the binding for Redux, synchronizing the state with Redux store maintaining unidirectional data flow.