Learn

By design, a Router will render all the Routes whose paths match the current URL. This allows us to compose layouts in which multiple components should appear or disappear based on the current URL (for example, an application in which the sidebar and main display respond to changes in the current URL). But sometimes, this design choice can produce unintended results.

Consider the following (relatively common) setup:

<Router> <div> <Route path='/articles/new'> <NewArticle /> </Route> <Route path='/articles/:title'> <Article /> </Route> <Route path='/articles'> <Articles /> </Route> </div> </Router>

What should happen when the user navigates to 'articles/new'? The NewArticle component should appear, right?

What actually happens is that ALL routes match:

  • /articles/new matches exactly
  • /articles/:title will match new to the URL parameter :title
  • /articles will match because both begin with /articles.

Because all routes match, the application will render the NewArticle, Article, and Articles components simultaneously.

React Router provides several mechanisms for preventing this sort of unintended rendering. The first is the Switch component:

import { Switch } from 'react-router-dom';

When wrapped around a collection of routes, Switch will render the first of its child routes whose path prop matches the current URL.

<Switch> <div> <Route path='/articles/new'> <NewArticle /> </Route> <Route path='/articles/:title'> <Article /> </Route> <Route path='/articles'> <Articles /> </Route> </div> </Switch>

Because the Switch checks routes sequentially, the order in which Routes are rendered matters. Consider a similar example but with the order of the routes reversed:

<Switch> <div> <Route path='/articles/:title'> <Article /> </Route> <Route path='/articles/new'> <NewArticle /> </Route> <Route path='/articles'> <Articles /> </Route> </div> </Switch>

Now imagine that a user navigates to '/articles/new'. The Switch renders the first route with a matching path, '/articles/new' matches '/articles/:title', since :title is a dynamic segment. With the routes listed in this order, the NewArticle component will never render. In general, you can avoid this problem by listing routes from most- to least-specific.

Sometimes you may want to leverage React Router’s composability and render multiple routes simultaneously (this would prevent you from using a Switch component) while also ensuring your router distinguishes between static paths and paths including URL parameters. Consider the following example:

<Router> <div> <Route path='/'> <Home /> </Route> <Route path='/sign-up'> <SignUp /> </Route> </div> </Router>

Any path will match first route, so the the Home component will be rendered whether the user is at '/' or '/sign-up'. This might be ideal behavior if the component rendered by the '/' route should display regardless of the current route.

But what if you only want the Home component to be visible to users on the home page and not to those who have navigated to /sign-up? By using React Router’s exact prop on the first route, you can ensure that the route will match only if the current URL is an exact match.

<Route exact path='/'> <Home /> </Route>

Now, when a user visits /, the Home component will render. But when a user visits /sign-up, only the second route will match and only the SignUp component will render.

React Router provides a couple of additional props—strict and sensitive—on the Route component for fine-tuning when a particular route should match, however, these are used far less frequently than the exact prop.

Instructions

Task 1

If you navigate to /articles/objects, you will notice that the Article and Articles components both render. Let’s fix this by using a Switch component.

First, import the Switch component in App.js.

Hint

Import the Switch component from react-router-dom and wrap the existing routes in a Switch.


Task 2

Next, use a Switch component to wrap all of the Route components inside the <main> section. Organize your Route components such that only the Articles component renders when you visit '/articles' and only the Article component renders when you visit /articles/objects.

Hint

Make sure to organize your components from most specific to least specific. In this case, the Route with the path '/articles/:title' should be above the Route with the path '/articles'.

Take this course for free

By signing up for Codecademy, you agree to Codecademy's Terms of Service & Privacy Policy.
Already have an account?