We have been talked about how the old website works. Now let's recall about it again to emphasize why we need a library call React Router.
Back in the day, when we clicked on a link, we would go back to the server, ask for a new HTML page and that server would send back a response that contain HTML, CSS and JavaScript. In modern world, things are different. We request the page then all the navigation happens within our website. We don't need to talk to the server anymore!
The JS file or our library (React) allows us to manipulate the DOM. Now, our servers can focus on sending data instead of focusing on what view to render, what html page to send. We can just make API requests and get JSON data back, which is really convinient.
It makes changing the DOM or users interacting with your website faster because it doesn't have to go back and forth to communicate.
Don't you notice that, the app we have been done for a while only have one Home
component. Which pretty much comprise our entire app.
But what if we had multiple page components, like an ProductPage
component or ProfilePage
component that needed to be rendered depending on what you URL the user was at? This is what routing try to solve, and the routing library we use for our app is called React Router.
React Router is the de facto standard routing library for React. When you need to navigate through a React application with multiple views, you'll need a router to manage the URLs. React Router takes care of that, keeping your application UI and the URL in sync.
React is a popular library for creating single-page applications (SPAs) that are rendered on the client side. An SPA might have multiple views (aka pages), and unlike conventional multi-page apps, navigating through these views shouldn't result in the entire page being reloaded. Instead, we want the views to be rendered inline within the current page. The following features are expected in an SPA:
www.example.com/products
.example.com/products/shoes/101
, where 101 is the product ID.BrowserRouter
- A
that uses the HTML5 history API (pushState, replaceState and the popstate event) to keep your UI in sync with the URLRoute
- Its most basic responsibility is to render some UI when a location matches the route's pathLink
- Links provide declarative, accessible navigation around your applicationSwitch
- Renders the first child Route
or Redirect
that matches the location. Switch
is unique in that it renders a route exclusively (only one route wins).We're going to take a simple CoderNews with the routing as example.
The structure of the simple CoderNews look like this:
|-node_modules
|-public
|-src
|-pages
|-HomePage.js
|-Products.js
|-DetailPage.js
|-App.js
|-App.css
|-index.js
|-package.json
|-package-lock.json
You can install React Router using the command: npm install react-router-dom
Import BrowserRouter
from react-router-dom In index.js
import {BrowserRouter as Router} from "react-router-dom"
ReactDOM.render(
<Router>
<App />
</Router>,
document.getElementById('root')
);
BrowserRouter
is a component that wrap around our application. It gives our app all of the functionality of routing that this library provides.In App.js
:
import { Route} from "react-router-dom"
function App() {
return (
<>
<Route exact path="/" component={Homepage}/>
<Route path="/products" component={Products}/>
</>
);
}
Route
is a component that takes a couple of arguments. There are three main ones that we want to focus on are exact
path
and component
.component
will be the component that we want the route to render.path
will be a string that's equal to the path from the current place in our app. We are at the base of the app which the baseURL is localhost:3000
exact
can either take the value true
or false
=> What happend if we don't have exact?In App.js
:
import { Route, Switch} from "react-router-dom"
function App() {
return (
<Switch>
<Route exact path="/" component={Homepage}/>
<Route path="/products" component={Products}/>
</Switch>
);
}
Switch
component wrap around our Route
componentsexact
now.In React router, we have two main way to navigate. That is Link
component and history.push
Link
component
Link
component.Link
component lets us dynamically pass in the propertyto
, which is contained the string of where we want this link take us to.For example, in our HomePage.js:
import React from "react"
import {Link} from "react-router-dom"
const HomePage = ()=>{
return (
<div>
<h1>This is homepage</h1>
<Link to="/products">Go to Products page</Link>
</div>
)
}
export default HomePage
You might ask why don't we use a
tag?
a
link would actually force you to redirect and re-render the entire application, whereas using the React route Link
, we're just borrowing the URL to tell our application what to re render.Now let me introduce you a hook in React router, the useHistory
The useHistory
hook gives you access to the history
instance that you may use to navigate.
The history object allows you to manage and handle the browser history inside your views or components.
Example:
import React from "react"
import {Link, useHistory} from "react-router-dom"
const HomePage = ()=>{
const history = useHistory()
const handlePush =()=>{
history.push("/products")
}
return (
<div>
<h1>This is homepage</h1>
<Link to="/products">Go to Products page</Link>
<button onClick={handlePush}>Another way to Products page</button>
</div>
)
}
export default HomePage
Try the code above, and now we have another way to navigate our app.
We have learn the first hook useHistory
that is use for navigation. Now we're going to learn a new hook called useParams()
First we need to know what is params:
:id
param defined in the route in this example:In App.js
:
import React form "react"
import { Route, Switch} from "react-router-dom"
import Homepage from './pages/Homepage';
import ProductPage from './pages/Products';
import DetailPage from './pages/DetailPage'
function App() {
return (
<Switch>
<Route exact path="/" component={Homepage}/>
<Route exact path="/products" component={ProductPage}/>
<Route exact path="/products/:productId" component={DetailPage}/>
</Switch>
);
}
productId
is called paramsproducts
and then slash anything in this spot after.productId
value we want to be able to accessuseParams
hook here to access the dynamic pieces of the URL:in DetailPage
:
import React from 'react'
import { useParams } from 'react-router'
const DetailPage = () => {
const params = useParams() //use the hook and assign its value to params variable
const {productId} = params
console.log("productId",productId)
return (
<div>
This is detail Page
</div>
)
}
export default DetailPage
Then try to access the URL: http://localhosl:3000/products/123
then check the console on your browser to see what we get line 7
This is how we can access to that dynamic value from the URL, by using React router hook useParams
A little bit further, why we even care about that productId part? Because, as the name says, DetailPage is a page that will display all the information of that single product. To be able to find a single product data, we need its id to send a GET request to backend.
We keep using the News api to play around with routing
enter
and it will redirect to a SearchPage
with all the news that match the search keyword