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}/>