React – Routing

Routing is the process of managing different URL paths of the application. It is the basis of single-page apps in react.

We can route various components to different paths and URLs.

Some Examples:

1. Going to “/products” displays all the products. If we go to “/products/:productId,” only the product details with the given productId are displayed.

2. You can render a Home component on the root path “/” and render a Contact component on the path “/contact

One advantage of routing in React is that there is no browser or page refresh on URL or path changes. It gives the user a smooth experience of the entire application on a single page.

Router Installation

React does not come with any built-in routing solution. We will use the most standard and popular routing library for React. It is called “react-router-dom.” You must install This library in those projects that require routing.

So, run this command in your react project:

npm install "react-router-dom"

This will install the react-router library into your project and will be ready to use.

Setting up the router

Before we can use the features of the React router, we must first wrap the root App component with <BrowserRouter /> inside our index.js file.

index.js
  //… other imports
  import { BrowserRouter } from 'react-router-dom';
  // wrap the root component inside BrowserRouter
  ReactDOM.render(
 	 <BrowserRouter>
 		 <App />
 	 </BrowserRouter>
);

BrowserRouter is a component provided by the react-router. It will set up our routing settings and will take control of the browser’s history API. In short, it provides several routing features to the application. This is the first and most essential step to use the react-router.

Now there are different components of React Router, which we will learn one by one.

The <Route /> Component

The Route component renders a given component if its expected path matches the browser’s URL. You have to pass the path as a prop to <Route />.

The component or element, that you want to display/render on route match should be passed as a child to the Route component.

world.js
/* A simple component that we want to route on ‘/world’ */
export default World() {
return (
<div>
  <h3>Welcome to the world</h3>
  <p>Some paragraph…</p>
  </div>
      )
      }
      App.js
      import { Route } from ‘react-router-dom’;
      import World from ‘./world’;
        function App() {
        return (
        <div>
        <h1>Welcome To App</h1>
        {/* pass the path property to Route */}
        <Route path='/world'>
      {/* This will only render if the path matches any browser URL starting with /world */}
      <World />
  </Route>
  </div>
  )
}
export default App

You can use any number of <Route /> inside the same component. Each of them will only render if the browser’s URL starts with their given path prop.

Route’s Exact Property

You can use an exact prop on the Route component to avoid matching similar route patterns.

Usually, Route checks if the browser URL starts with the passed path prop. It does not check for equality of the path unless exact is used.

Here, the above Route will match exactly the path '/world'.

<Route path='/world' exact>
    <World />
</Route>

If you don’t use the exact keyword, it will match any URL path starting with ‘/world’. Example: ‘/world/hello’, ‘/world/one/two’, etc., will activate the Route component, and <World /> will be rendered.

The <Switch /> Component

There are chances that multiple Route components may be triggered if the exact prop is not used. For instance, both the routes will be rendered on navigating to ‘/world’:

<Route path='/world'>
<World />
</Route>
<Route path=’/’>Root</Route>

If we want to render only the first of the matching routes, we need to wrap them inside a <Switch /> component.

So, even if multiple routes match, Switch will guarantee that only the first of the routes render that are wrapped inside it.

import { Route, Switch } from 'react-router-dom'
// other code…
    <Switch>
      <Route path='/world'>
      	<World />
      </Route>
    <Route path='/'>Root</Route>
</Switch>

Importance of Route Order inside <Switch />

The route matches are performed in a top to bottom fashion. So make sure to put more specific routes like ‘/world’ first than ‘/’.

If you put '/' Route at the top of the Switch will always render the Route with the '/' path for any URL. This is because all URLs start with a slash ('/'), and the Switch executes only the first matching Route in order.

However, you can combine the exact prop on Route with the Switch component. If you do that, you can define routes in any order without an issue.

The below code will work as expected.

<Switch>
  <Route path='/' exact>Root</Route>
  	<Route path='/world'>
  <World />
  </Route>
</Switch>

The <Link /> Component

It is annoying to type the URL manually in the address bar. You can create hyperlinks using the anchor tag(<a>), but it will refresh the page every time.

Therefore in React, create hyperlinks using only the <Link /> component from the react-router. It does not cause any page refresh and updates the browser URL appropriately when clicked.

import { Route, Switch, Link } from 'react-router-dom'
  // your previous route, switch code here…
  /*
  Always use the <Link /> component to navigate between routes in your app. <Link /> takes a to prop which is the path to navigate when clicked.
  */
  <Link to='/'> Go to Root </Link> <br />
  <Link to='/world'> Go to world </Link> <br />
  // Don’t Use! a href works the same as Link but causes page to refresh.
<a href=’/world’> Href link to world </a>

Styling Your Links

You can style your links however you like by adding a className prop to the <Link /> component and writing CSS rules for that.

app.js
  import './style.css'
  // your code
  <Link className='my-link'>Home</Link>
  style.css
  .my-link {
  color: red;
  background: yellow;
}

The Router Instance

Do you remember that we used the <BrowserRouter /> at first to wrap our <App /> component?

BrowserRouter allows us to use the essential routing features. It also provides us with a router instance that we can leverage for common use cases.

Using the router instance, we can read the current pathname, path parameters, query-string, redirect, and use the history object.

This instance is available to all the descendants of the <BrowserRouter /> component.

Properties of the Router Instance

The router object has three different properties: Location, Match, and History. All three of them are objects with useful properties and methods.

1. Location

The location object contains five different properties: hash, key, pathname, search, and state. The most useful ones are pathname and search.

location.pathname will return to the current path.

location.search will return the query string portion of the path.

2. Match

The match object contains the details of the matched path. It has four properties: isExact, params, path, and URL. It is useful to build dynamic routes that we will discuss later.

3. History

The history object contains many methods. It has a .push() method that is useful to perform redirects programmatically.

Programmatic Redirect using history.push()

Just call the history.push(pathname) method to perform redirects. You can use it inside your class methods, event handlers, or any helper function that has access to props (as history is stored inside props).

// inside a class method or a helper function
    function authenticateUser(user){
    if(user.loggedIn){
    // redirect the user to the dashboard page…
    props.history.push('/dashboard');
    }
}

Accessing The Router Instance Properties

You can access the router instance properties as props inside any descendant component of the <BrowserRouter />. For that, wrap your component inside the withRouter() function from the react-router library.

import { withRouter } from 'react-router-dom'
    function MyComponent(props) {
    /*
    Props will now contain three additional properties: history, location, pathname passed by withRouter().
    */
    console.log(props.location, props.pathname, props.match);
    }
export default withRouter(MyComponent);

Dynamic Routes

Routes can also take parameters and use that information to display a specific component.

Example: If the path is /products/:productName

Then,

/products/phone route will render a particular phone product.

/products/camera route will render that particular camera product.

The part of the Route with :productName is the route/path parameter name. Its value is determined dynamically for different URLs.

To use dynamic routes, define the dynamic path in the Route component like so:

App.js
import Product from './Product.js'
import { Route } from 'react-router-dom'

// route with dynamic path
<Route path='/products/:productName' exact>
{/* this route will match anything that starts with /products/somevalue*}
    <Product />
    </Route>
    You can access its value inside the product component using props.match.params.productName
    Product.js
    import { withRouter } from 'react-router-dom'
    function Product(props) {
    const routeParams = props.match.params;
    // access the product name from the match object
    const productName = routeParams.productName;
    return (
        <h1>
        	Product name: { productName }
        </h1>
    )
    }
export default withRouter(props);

Summary

Routing is a major part of any web application. The React Router gives us invaluable features that help us design and route components according to our requirements.

For small-scale apps, routing is simple, but routing can get tricky for large-scale apps, and you must plan for it properly.

Back to: React Tutorial > Advanced Topics in React

Leave a Reply

Your email address will not be published. Required fields are marked *