Many modern websites are actually made up of a single page, they just look like multiple pages because they contain components which render like separate pages. These are usually referred to as single-page application (SPA).
React Router is a client-side routing to build a single-page application (SPA) that allows navigation between different pages without refreshing the browser.
In this article we will shows you how to build a simple single-page application (SPA) using React Router.
Prerequisites
We expect that you are familiar with the following:
- JavaScript (Basic level)
- ReactJs (Basic level, must understand What is Component)
Expected Learnings
Your key learnings from this project will be:
- A basic example of the React Router to get you started
- Examples of each React Router hook to understand its use
Step 1: Setting Up a React Project
To get started, we need to create a new React app using NPM. Please run the following command in your terminal:
npx create-react-app react-router-tutorial
This command creates a new React project in your machine. It could takes few minutes for the creating process.
Once it was finished, please navigate to the react-router-tutorial folder to modify App.js file.
Step 2: Modifying App.js File
We will create 3 different components in the App.js file: Home, About & Shop. Moreover, we’ve added <nav> as navigation for navigating through these pages.
import './App.css';
import { Fragment } from 'react';
function App() {
return (
<main>
<nav>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/shop">Shop</Link></li>
</ul>
</nav>
</main>
);
}
const Home = () => (
<Fragment>
<h1>Home</h1>
<LoremText />
</Fragment>
)
const About = () => {
return (
<Fragment>
<h1>About</h1>
<LoremText />
</Fragment>
)
}
const Shop = () => {
return (
<Fragment>
<h1>Shop</h1>
<LoremText />
</Fragment>
)
}
const LoremText = () => (
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
)
export default App;
Step 3: Setting up React Router
To use React Router in React app, first we need to install it via NPM:
npm install --save react-router-dom
Then, import the Router object into our App.js file. Once that is done, we can use the Router object to wrap the entire application as we want routing to be available everywhere in our application.
import './App.css';
import { Fragment } from 'react';
import { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom';
function App() {
return (
<Router>
<main>
<nav>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/shop">Shop</Link></li>
</ul>
</nav>
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route exact path="/about">
<About />
</Route>
<Route exact path="/shop">
<Shop />
</Route>
</Switch>
</main>
</Router>
);
}
const Home = () => (
<Fragment>
<h1>Home</h1>
<LoremText />
</Fragment>
)
const About = () => {
return (
<Fragment>
<h1>About</h1>
<LoremText />
</Fragment>
)
}
const Shop = () => {
return (
<Fragment>
<h1>Shop</h1>
<LoremText />
</Fragment>
)
}
const LoremText = () => (
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
)
export default App;
Refactored the <a> tags in the <nav> section to the <Link> tags to prevent page refresh when you click on it. The <Link> tag doesn’t trigger a page refresh while the <a> tag naturally does.
Next, we use <Switch> tag to instruct React Router to switch to the exact Route when user click on each <Link> tag. For instance, the path / loads Home, the path /about loads About and the path /shop loads Shop component.
Save your code, and reload the page in browser.
You should see the navigation and the navigation works as expected.
Step 4: Using React Router Hooks
React Router offers several hooks that allow React developers to use the in-built functions, such as useHistory, useParams, useLocation and useRouteMatch.
useHistory hook: gives us access to the history instance that we may use to navigate. We can then call methods on the history object like goBack or push, for example:
import { useHistory } from "react-router-dom";
function HomeButton() {
let history = useHistory();
function handleClick() {
history.push("/about");
}
function handleBackClick() {
history.goBack();
}
return (
<button type="button" onClick={handleClick}>
Go About Page
</button>
<button type="button" onClick={handleBackClick}>
Back to Previous Page
</button>
);
}
useParams hook: returns an object of key/value pairs of URL parameters. Use it to access match.params of the current. Example:
import { useParams } from 'react-router';
function App() {
return (
<Router>
<Link to="/blog/1">Blog Post 1</Link>
<Switch>
<Route exact path="/">
<HomePage />
</Route>
<Route path="/blog/:slug">
<BlogPost />
</Route>
</Switch>
</Router>
);
}
const BlogPost = () => {
const params = useParams();
const current = param.id;
return (
<div>
<p>You requested item with ID: {current}</p>
</div>
)
}
const Home = () => (
<div>Home</div>
)
useLocation hook: returns the location object that represents the current URL. You can think about it like a useState that returns a new location whenever the URL changes. You can use it, for instance, to trigger a new page view event for a web analytics tool. Example:
import { useLocation } from "react-router";
// About Page
const About = () => {
const location = useLocation();
// Fictive call to Google Analytics
// ga.send(["pageview", location.pathname])
console.log(location.pathname);
return (
<div>
<h1>About</h1>
<LoremText />
</div>
);
};
In the following example, we will take a closer look on how to useRouteMatch for the page that we made.
The useRouteMatch hook attempts to match the current URL in the same way that a <Route> would. It’s mostly useful for getting access to the match data without actually rendering a <Route>.
In our case, we will use useRouteMatch hook for the Shop page. Imagine, there are plenty of product inside the Shop page, we want to render all products at once when the URL doesn’t contain an ID, e.g. /shop, and render a specific product when the URL contain an ID e.g. /shop/:id
So, before we can use the useRouteMatch hook, we have to import it into App.js.
import './App.css';
import { Fragment } from 'react';
import { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom';
import { useRouteMatch } from 'react-router';
function App() {
return (
<Router>
<main>
<nav>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/shop">Shop</Link></li>
<li><Link to="/shop/1">Product 1</Link></li>
</ul>
</nav>
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route exact path="/about">
<About />
</Route>
<Route path="/shop">
<Shop />
</Route>
</Switch>
</main>
</Router>
);
}
const Home = () => (
<Fragment>
<h1>Home</h1>
<LoremText />
</Fragment>
)
const About = () => {
return (
<Fragment>
<h1>About</h1>
<LoremText />
</Fragment>
)
}
const Shop = () => {
const routeMatch = useRouteMatch('/shop/:id');
const returnRouteMatch = routeMatch ? `You requested item with ID: ${routeMatch.params.id}` : 'All product';
return (
<Fragment>
<h1>Shop</h1>
<p>{`${returnRouteMatch}`}</p>
</Fragment>
)
}
const LoremText = () => (
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
)
export default App;
Then we pass the path we want to verify to the useRouteMatch hook: /shop/:id. If the route matches, we render the product page. We can access the product ID via routeMatch.params.id.
Next, make sure you remove exact from the <Route>. The exact is a boolean. When TRUE, will only match if the path matches the location.pathname exactly. Example:
path | location.pathname | exact | matches? |
/one | /one/two | true | no |
/one | /one/two | false | yes |
So for our case, we have to remove it, because we want to use back the same Shop page, regardless of /shop or /shop/:id
Next, remember to add an extra link that redirects us to the Shop’s specific product page. Both the /shop and /shop/1 links are connected to the component.
Save your code and refresh the browser, you should see how the useRouteMatch hook works!
That’s it!
In the next post, we will talk about how to add simple transition when navigating to different pages! Click here to read Adding Animated Transition To React Router
Follow onlyWebPro.com on Facebook now for latest web development tutorials & tips updates!