React/ReactJS: Router
Navigation between pages is indespensible part of any web application. There are various ways to set up routing in ReactJS. In this tutorial, we pick react-router
, a popular declarative component-based router.
Since v4, it has been sub-categorized into three packages: react-router
, react-router-dom
, and react-router-native
. The first package, react-router
, is the root package of them all; the other two are environment-specific (depends on whether you are creating a geneic website or a mobile app). If you are building a website, use react-router-dom
, but if you are building a mobile app in React Native, use react-router-native
.
For our purpose here, we choose react-router-dom
.
Install the react-router-dom
package.
npm install react-router-dom --save
<HashRouter/>
v/s <BrowserRouter/>
Now there are two router components to go about from here:
- <HashRouter/>
- <BrowserRouter/>
The difference between the two is mainly in the URLs they generate.
<HashRouter/>
relies on hashes (window.location.hash
) to sync UI with the URL. This component is suitable for static websites. AngularJS old timers will find it familiar.
//<HashRouter/>
http://localhost:3000/#/about
<BrowserRouter/>
uses HTML5 history API to keep the component UI in sync with the URL. There are no hashes in the URL.
//<BrowserRouter/>
http://localhost:3000/about
For the purpose of our tutorial, we will choose <HashRouter/>
.
Configuring Router
The configuration shown below is to be done in the index.js
file.
Create two functional components <About/>
and <Services/>
, each returning a single <h1>
element containing the texts "About" and "Services" respectively.
import React from 'react';
import ReactDOM from 'react-dom';
const About = () => {
return (
<h1>About</h1>
);
}
const Services = () => {
return (
<h1>Services</h1>
);
}
The goal is to load each of these components separately on click of some links configured to them specifically.
We next import HashRouter
and Route
from react-router-dom
into index.js
. Now instead of the usual App
component, set up the HashRouter
and Route
components inside render()
as follows.
import React from 'react';
import ReactDOM from 'react-dom';
import { HashRouter, Route } from 'react-router';
const About = () => {
return (
<h1>About</h1>
);
}
const Services = () => {
return (
<h1>Services</h1>
);
}
ReactDOM.render(
<HashRouter>
<div>
<Route path="/about" component={About}/>
<Route path="/services" component={Services}/>
</div>
</HashRouter>
, document.getElementById('root'));
NOTE: Notice the <div/>
element child of <HashRouter>
. That is because a router component can have only a single child element, and all the <Route/>
elements are wrapped inside it.
Link
Next we import Link
to provide accessible navigation, which actually is quite akin to the <a>
tag. We construct one more functional component called <App/>
to implement the Link
component as shown below. Also note that we create a new route for it, with the path
attribute set to /
, which is the home/landing page.
import React from 'react';
import ReactDOM from 'react-dom';
import { HashRouter, Route, Link } from 'react-router-dom';
const About = () => {
return (
<h1>About</h1>
);
}
const Services = () => {
return (
<h1>Services</h1>
);
}
const App = () => {
return (
<div>
<ul>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/services">Services</Link>
</li>
</ul>
</div>
)
}
ReactDOM.render(
<HashRouter>
<div>
<Route path="/" component={App}/>
<Route path="/about" component={About}/>
<Route path="/services" component={Services}/>
</div>
</HashRouter>
, document.getElementById('root'));
It is a simple set-up without any styling. It gets rendered as below:
Now if you click on any of the link, About
or Services
, the respective components will load — but along with the component specified for the default /
path. The loaded pages look as follows:
This actually is unwanted (and could have avoided had we used <BrowserRouter/>
in place of <HashRouter/>
). But there is an easy way out of it; we just have to add the exact
props to the <Route/>
component.
Adding the exact
props
We add it to the first (default) component above.
<Route exact path="/" component={App}/>