Learn

In the previous exercise, we created a nested Link and Route in the Categories component.

// Ex: Create a link for the '/categories/html' page <Link to={`/categories/${category}`}> {category} </Link> ... // Ex: When the user visits `/categories/html`, a Category component is rendered <Route path={'/categories/:categoryName'}> <Category /> </Route>

Route nesting improves the organization of Link and Route components in our application. As in the Categories component, it is common that nested Link and Route components stem from the same base URL (in this case, the /categories URL).

Instead of writing out the full URL path, it would be much more flexible if we could create relative paths based on the /categories URL. React Router provides a hook, useRouteMatch(), that makes it incredibly easy to do this.

Below, you can see the basic usage in a component called BandPage that gets rendered by the route '/bands/:band/'. Suppose that the user visits the page /bands/queen/. This page should render a list of relative Links based on the various songs by the band Queen. A Route is also created to render a SongPage for any chosen song:

import { useRouteMatch, Link, Route } from 'react-router-dom'; import { SongPage } from '../SongPage.js' function BandPage ({ songs }) { let { path, url } = useRouteMatch(); // path = '/band/:band' // url = '/band/queen' // Render a list of relative Links and a Route to render a SongPage return ( <div> <ul> { songs.map(songName => <li> <Link to={`${url}/song/${songName}`}> {category} </Link> </li> ) } </ul> <Route path={`${path}/song/:songName`}> <SongPage /> </Route> </div> ) }

Let’s break this down.

  • useRouteMatch() should be called inside a component and returns an object with a url and a path property. This object is sometimes referred to as the match object:
  • The path property contains the dynamic path pattern with URL parameters (eg. /bands/:band) and should be used for creating relative path props for Route components (eg. /bands/:band/songs/:songName)
  • The url property has the values of URL parameters filled in (eg. /bands/queen) and should be used for creating relative to props for Link components (eg. /bands/queen/songs/we_are_the_champions).

Let’s see how we can use these values within the Categories component to create relative routes to the Category component:

import { Link, Route, useRouteMatch } from 'react-router-dom' function Categories ({ categories }) { let { path, url } = useRouteMatch(); // path = '/categories' // url = '/categories' // Even though path and url are the same in this case, use path for relative Routes and url for relative Links return ( <div> <ul> { categories.map(category => <li> <Link to={`${url}/${category}`}> {category} </Link> </li> ) } </ul> <Route path={`${path}/:category`}> <Category /> </Route> </div> ) }

Using the relative url and path values to generate the Link and Route components ensures that they accurately route the user to the correct URL regardless of the route that caused the Categories component to render.

Instructions

Task 1

Let’s now return to the Profile component. We want to use relative paths to construct the Link and Route components for the EditProfileForm component.

In src/components/Profile.js, import useRouteMatch from react-router-dom.

Hint

You can either add useRouteMatch to the list of existing imports, or import it on its own.


Task 2

Next, inside the Profile component, use destructuring assignment to get the url and path properties from the object returned by useRouteMatch.

Hint

Your code should look something like this:

const { valueA, valueB } = useRouteMatch();

Task 3

Refactor the Route and Link components by replacing hard-coded instances of /profile with the path and url values from useRouteMatch as appropriate.

Hint

Though both path and url will have the same value ('/profile'), it’s important to consistently use path when constructing Route components, and url when constructing Link components.

Your code may look like this (using plain string concatenation):

<Link to={url+"/edit"}>Edit</Link> <Route path={path+"/edit"}> <EditProfileForm /> </Route>

or like this (using template literals):

<Link to={`${url}/edit`}>Edit</Link> <Route path={`${path}/edit`}> <EditProfileForm /> </Route>

Note: The url and path values are mixed up in the video!

Take this course for free

Mini Info Outline Icon
By signing up for Codecademy, you agree to Codecademy's Terms of Service & Privacy Policy.

Or sign up using:

Already have an account?