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.
Link
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
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 }
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>
}
Pass props to React Router v5 Link Component
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.