A guide to using React Router in React apps

A guide to using React Router in React apps

I am sharing my React Router V5 Notes as a blog. you can use this blog as a quick refresher of react-router.

Bowser Router

There are certain times when router components need to send router props to components. Bowser router leverages context API under the hood the achieve that. So the first thing to do when using react-router is to wrap the main component with the browser router.

<BrowserRouter>
    <App/>
</BrowserRouter>

Route

Route component will render the child component when a URL matches a specified path.

      <Route exact path="/">
        <Home />
      </Route>
      <Route exact path="/about">
        <About/>
      </Route>

As react-router v5 allows partial matching it can even render multiple components if their path matches even partially so it is important to use the exact prop because it only renders the component if the path matches exactly to the specified path in Route path prop.

After specifying the routes the next step is to navigate between them and the react-router way of doing this is to use the Link component. Link can be understood as an equivalent of the anchor tag. In the Link component, there is to prop which specifies the path to navigate to.

// link to about page
<Link to="/about">About</Link>

Dynamic Routing and use params

useParam is a hook that helps in accessing the dynamic part of the URL in a component

For example: render a twitter id

Route

<Route path="/:handle">
    <Account/>
</Route>

Component

Import {useParams} from ‘react-router-dom’;
Const Account = () => {
// accessing the dynamic URL
   Const {handle} = useParams()
   return (<h1> {handle} </h1>)
}

Nested Routes

The route component will always render something, either a component if the path matches or null. It doesn’t matter if you render a Route in your main component or in a child component, if the path matches the app’s location, the children element will be rendered

Now suppose we want to go to /topics/:id so we can use something like

<Link to="/topics/:id">{Topic}</Link>

This will get the job done but if topics are changed to concepts or anything else in the main component the there will be an error so to avoid that useRouteMatch hook is used.

useRouteMatch returns an object which contains information about how the Route was matched. Specifically, it has two properties, a path, and a URL.

path - The path pattern used to match. Useful for building nested s

url - The matched portion of the URL. Useful for building nested s

Assume we were using an app that had nested route’s and the current URL was /topics/react-router/url-parameters. If we were to use useRouteMatch and log path and URL in the most nested component, here’s what we would get.

const { path, url } = useRouteMatch()

console.log(path) // /topics/:topicId/:subId
console.log(url) // /topics/react-router/url-parameters

The path includes the URL parameters while the URL contains the full URL that’s why one is used in Route and another in Link

Pass Props to a component rendered with react-router

we can use the render prop in route to pass props to a component

<Route
  path='/dashboard'
  render={(props) => (
    <Home {...props} isLoggedIn={true} />
  )}
/>

Also In react-router 5 instead of using a component, we can pass the component as a child so passing props with a react-router is the same as passing props to a child component.

<Route path=”/”>
  <Component props={prop}/>
</Route>

Programmatically navigate with react-router

There are 2 ways to programmatically navigate

React way with Redirect User Input -> state Change -> re-render

function Register () {

const [toHome, setToHome] = React.useState(false)

if (toDashboard === true) {
   return <Redirect to='/home' />
}

return (
         <div>
           <h1>Register</h1>
           <Form afterSubmit={() => toHome(true)} />
          </div>
  )
}

useHistory hook If we want to use the imperative way to navigate. We can use useHistory hook and history.push(“/url”).

import React from 'react'
import {useHistory } from ‘react-router-dom’

function Register () {
const history = useHistory();
  return (
    <div>
      <h1>Register</h1> 
   <Form afterSubmit={()=>history.push(‘/dashboard’)} />
</div>
  )
}

Query Strings with React Router

let see how to get the query parameters from the URL.

For eg:- xyz.com?name=keshav&age=21

To get the query parameters value (name and age) in the code we can use useLocation hook • useLocation returns a location object which has a search property

Const {search} = useLocation();

Console.log(search);
// ?name=keshav&age=21

search property doesn’t return the parsed values of the query parameter so we have to do that on our own

Ways to parse the query parameters returned from the search

  1. Use NPM Package

    Use queryString npm package

    Import queryString from ‘query-string’;
    
    function Details () { 
    Const {name,age} = queryString(search);
    // now use name and age in code anyway you want 
    }
    
  2. Use a Browser's built-in way

    Use browser built-in urlSearchParameter

    function Details () { 
     const searchParams = new urlSearchParameter(search)
     const name = searchParams.get(‘name’)
     const age = searchParams.get(‘age’)
     // now use name and age in code anyway you want 
    }
    

Handling 404 pages (catch all routes)

In switch, component put a route at the end that allows all routes so what will happen if no routes match with the above routes then the last route can re-render a 404 page or anything that you like.

<Switch>
 <Route path=”/” exact>
   <Home />
 </Route>
<Route path=”*” >
   <FouruhFourPage />
 </Route>
</Switch>
`

Any route other than “/” will be handled by FouruhFourPage.

Const FouruhFourPage = () => {
  Const {pathname} = useLocation()

  <h3>No match for <code> {pathname} </code></h3>
}

Now let's see how to pass with state with Link component in order to use that state in the Route being rendered.

The first way is to use URL parameters and useParams hooks

Url parameters are a good way for the passing strings but they aren’t meant for any other data types.

Another way is to send an object in place of a string in to prop of the Link component. For eg:

<Link
  to={{
    pathname: "/keshav",
    state: {
      fromNotifications: true,
    },
  }}
>
  Keshav Jha
</Link>

How to access the above state in a component

Below 2 lines are enough to access the data in a state object in any functional component but don't forget to import useLocation from react-router-dom.

const location = useLocation()  
const { fromNotifications } = location.state

Thanks for reading the blog and If you found something wrong feel free to comment on that and I will be happy to edit that.