React Router
#
Learning Objectives- Use React Router's
BrowserRouter
,Link
,Route
,Redirect
, andSwitch
components to add navigation to a React application - Review the React component lifecycle and use component methods to integrate with API calls
- Talk about SPAs
#
FramingUp to this point, our React applications have been limited in size, allowing us to use basic control flow in deciding what components to render. However, as our React applications grow in size and scope, we need an easier and more robust way of rendering different components.
We will replace standard conditional logic with the ability to render components based on the url.
React Router is the most commonly-used routing library for React. It is relatively straightforward to configure and integrates with the component architecture nicely (since it's just a collection of components).
We will configure it as the root component in a React application. Then we'll tell it to render other components within itself depending on the path in the url. This way we don't have to reload the entire page to swap out some data.
#
React Bitcoin PricesHere is what we are looking to build: Bitcoin Solution Code
#
Provider/Consumer ModelDuring the introduction of useContext
we first took a look at the Provider/Consumer
model that was happening under the hood of a React app that was using React Router.
Let's take a minute once again to open the solution code and view that model again in React DevTools.
BrowserRouter
Router
Router.Provider
App
Link
ForwardRef
Router.Consumer
LinkAnchor
ForwardRef
LinkForwardRef
Router.Consumer LinkAnchorForwardRef
Switch
Route.Consumer
#
React Router SetupHere is our Starter Code
https://codesandbox.io/s/bitcoin-starter-swwzg
Let's bring in React Router and set it up to allow us to display multiple components.
#
⏰ Activity - 2minLets take a look at the React Router Documentation first before we get started.
#
Importing DependenciesFirst, we need to install the following:
react-router
react-router-dom
#
Setting Up React RouterThere are several Components that will need to make use of from the React Router library.
Router
#
React Router first provides us the Router
component. It talks to the browser and allows us to create history
(the ability to use the forward/back buttons) with our app, even though we are still on a single-page app. It also provides us the ability to update the URL to redirect by updating the history object.
As with a components render()
method the Router
component also expects to receive only one child element. The child element can have routes defined or those routes could be even nested further.
Route
#
The React Router Route
component allows us to define a URL endpoint and describe what should load on the page at that point.
#
Import and Setup RouterWe need to import the Router
into index.js
and place it as the root component of our application. Router
will,
in turn, render App
through which all the rest of our components will be rendered:
The actual Component name is called BrowserRouter
however we will take the liberty of renaming it Router
#
index.jsimport { BrowserRouter as Router } from "react-router-dom";
And now we wrap it around the App
Component so that we can make full use or routing.
ReactDOM.render( <Router> <App /> </Router>, document.getElementById("root"));
By making Router
the root component of our app, it will pass down several
router-specific objects to any components that rendered via Router
.
Things like current location and url can be accessed or changed. Additionally, in order to use the other
routing components provided by React Router, a Router
parent component is necessary.
#
Working With Route#
App.jsNext, in App.js
let's import the Route
Component
A Route
has defined props that tell it what route to look for but also what to do once that route has been matched.
Here are the props available to Route
:
path
- the url that should be matchedcomponent
- the component that should be renderedrender
- jsx that is rendered directly in the route
Let's first import Route
import { Route } from "react-router-dom";
And now configure it to render the default route of Home
.
return ( <div> <nav> <a href="/"> <img src="https://en.bitcoin.it/w/images/en/2/29/BC_Logo_.png" alt="" /> <h1>Bitcoin prices</h1> </a> <a href="/currencies">Currencies</a> </nav> <main> <Home /> <Route path="/"> <Home /> </Route> </main> </div>);
If we leave both references to Home
then React will render both of those Components. One is hard coded to render and the other is being rendered via the route defined in path
.
So let's comment out <Home />
for now.
<main> {/* <Home /> */} <Route path="/"> <Home /> </Route></main>
Great! But this doesn't do anything because we're already on the homepage.
This does however pass down to several new props to Home
which we can see in DevTools.
#
Location and MatchBoth location
and match
display info about the route.
location: { hash: "", pathname: "/", search: "", state: undefined}
hash: ""
pathname: "/"
search: ""
state: undefined
match: { isExact: true, params: {...}, path: "/", url: "/"}
isExact: true
params: {}
path: "/"
url: "/"
#
History But history
provides us with several useful methods to manipulate the route.
history: { isExact: true, params: {...}, path: "/", url: "/"}
action: "POP
block: f block() {}
createHref: f createHref() {}
go: f go() {}
goBack: f goBack() {}
goForward: f goForward() {}
length: 1
listen: f listen() {}
location: { hash: "", pathname: "/", search: "", state: undefined}
push: f push() {}
replace: f replace() {}
Currencies
Route#
Adding The First let's import the Currencies
Component
import Currencies from "../Currencies/Currencies";
And now we add the route
return ( <div> <nav> <a href="/"> <img src="https://en.bitcoin.it/w/images/en/2/29/BC_Logo_.png" alt="" /> <h1>Bitcoin prices</h1> </a> <a href="/currencies">Currencies</a> </nav> <main> <Route path="/"> <Home /> </Route> <Route path="/currencies"> <Currencies /> </Route> </main> </div>);
Now we've got two components and two route and both have be activated by clicking on the links in the nav. Two things to note however are:
- the page refreshes every time we toggle between the links
- both the Home and Currencies components are being displayed simultaneously
Let's first deal with the first issue import and use the <Link>
Component.
<Link>
#
Using Let's first import Link
import { Route, Link } from "react-router-dom";
And now we replace the anchor tags with <Link>
and were all set.
return ( <div> <nav> <Link to="/"> <img src="https://en.bitcoin.it/w/images/en/2/29/BC_Logo_.png" alt="" /> <h1>Bitcoin prices</h1> </Link> <Link to="/currencies">Currency List</Link> </nav> <main> <Route path="/"> <Home /> </Route> <Route path="/currencies"> <Currencies /> </Route> </main> </div>);
#
Using Exact KeywordNow we will resolve the second issue by including the exact keyword in the default route.
<main> <Route exact path="/"> <Home /> </Route> <Route path="/currencies"> <Currencies /> </Route></main>
#
RedirectsRedirects using react router are incredibly easy. Redirect is just another component we can import and use by passing it a few props.
Let's create a route to handle if/when a user manually types in a route that doesn't exist.
<main> <Route exact path="/"> <Home /> </Route> <Route path="/currencies"> <Currencies /> </Route> <Redirect to="/" /></main>
And it looks like we are done for now.