If you decide to use React for your application, you will likely be building a Single Page Application(SPA). As your application grows, you will want your app to have multiple URLs that contain different components. This is where client-side routing comes in.
The major benefit of client-side routing is speed. Using client-side routing, the whole application is loaded on the first GET request. Because of this, it can take a while when the application first mounts, but then we don't have to wait for a round trip server call for each page change after that.
React Router is the most popular routing library for React. It allows you to create intuitive routes that are human-readable so it will be easy to manage the application structure.
I am going to walk you through how to implement client-side routing in a React application using React Router step by step.
Installation
In your application, run this:
$ npm install --save react-router-dom
Or, if you are using yarn, run:
yarn add react-router-dom
Implementation
Add routes
Let's first create the <Home> page and add /home routes in our application so we can go to http://localhost:3000/home to see the <Home> page.
Here is our simplest <Home> page:
// myapp/src/components/Home.js
import React from 'react'
const Home = () => {
return (
<>
<h1>Home page</h1>
<h3>Welcome to my app!</h3>
</>
)
}
export default Home
Now, in App.js, let's set up a route to load the Home component:
// myapp/src/App.js
import React from 'react'
import { BrowserRouter, Route } from 'react-router-dom'
import Home from './components/Home'
const App = () => {
return (
<>
<h1>My App</h1>
<BrowserRouter>
<Route path="/home" component={Home} />
</BrowserRouter>
</>
)
}
export default App

Great! The <BrowserRouter> component creates a base router and the <Route> component configures each route and specifies the component that should render.
Let's also create <AboutUs> and <Contact> pages and add /about and /contact routes as well:
// myapp/src/components/AboutUs.js
import React from 'react'
const AboutUs = () => {
return (
<h1>About us</h1>
)
}
export default AboutUs
// myapp/src/components/Contact.js
import React from 'react'
const Contact = () => {
return (
<h1>Contact page</h1>
)
}
export default Contact
// myapp/src/App.js
import React from 'react'
import { BrowserRouter, Route } from 'react-router-dom'
import Home from './components/Home'
import Contact from './components/Contact'
import AboutUs from './components/AboutUs'
const App = () => {
return (
<>
<h1>My App</h1>
<BrowserRouter>
<Route path="/home" component={Home} />
<Route path="/about" component={AboutUs} />
<Route path="/contact" component={Contact} />
</BrowserRouter>
</>
)
}
export default App
Exact path

Hmmm, this is not exactly what we want. We want to show <Contact> page only when we go to /contact. In this case, we can use the exact attribute:
// myapp/src/App.js
import React from 'react'
import { BrowserRouter, Route } from 'react-router-dom'
import Home from './components/Home'
import Contact from './components/Contact'
import AboutUs from './components/AboutUs'
const App = () => {
return (
<>
<h1>My App</h1>
<BrowserRouter>
<Route path="/home" component={Home} />
<Route path="/about" component={AboutUs} />
<Route exact path="/contact" component={Contact} />
</BrowserRouter>
</>
)
}
export default App

Great! Now /contact/something path doesn't render <Contact> component.
Use <Switch> to set up exclusive routes
What if you change your mind and you want to add home/about instead of /about? Sure, we can do that. But first, you need to know how <Switch> works.
<Switch> works as the switch statement in JavaScript. It checks the path, and, as soon as it finds a match, it breaks out of the block. Let me show you what would be a problem without using <Switch>:
// myapp/src/App.js
import React from 'react'
import { BrowserRouter, Route } from 'react-router-dom'
import Home from './components/Home'
import Contact from './components/Contact'
import AboutUs from './components/AboutUs'
const App = () => {
return (
<>
<h1>My App</h1>
<BrowserRouter>
<Route path="/home" component={Home} />
<Route path="/home/about" component={AboutUs} />
<Route exact path="/contact" component={Contact} />
</BrowserRouter>
</>
)
}
export default App

Oh no. Why do we see the <Home> component too? This happens because of the way JavaSript matches strings.
> "/home".match("/home/about")
null
If I match /home with /home/about, it returns null. On the other hand, if I match /home/about with /home:
> "/home/about".match("/home")
[ '/home', index: 0, input: '/home/about', groups: undefined ]
I get a truthy value. This is why /home/about renders both <Home> and <AboutUs> components. We can avoid this using <Switch> because it breaks after the first match found. Don't forget to put the most specific routes first and more general routes second since <Switch> matches from the top.
// myapp/src/App.js
import React from 'react'
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import Home from './components/Home'
import Contact from './components/Contact'
import AboutUs from './components/AboutUs'
const App = () => {
return (
<>
<h1>My App</h1>
<BrowserRouter>
<Switch>
<Route path="/home/about" component={AboutUs} />
<Route path="/home" component={Home} />
<Route exact path="/contact" component={Contact} />
</Switch>
</BrowserRouter>
</>
)
}
export default App
In the next article, I will introduce how to set up routes with parameters using React Router.



Top comments (0)