You have to stick to the route to reach your destination. In this article we will explore about the react-router-dom package to create routing in React.
Let us continue our journey with React and understand how to make routes. This one will be straight forward and simple as we have to create bunch of routable components. The complexity arrives when we do authorized routes, but that we will keep for future. Routing is not something comes from within React, for routing we will be needing a third-party package, out of many the most suitable is React Router Dom and the NPM link can be found here.
We will head in this direction:
For our Notesy app we will have 2 pages, one is Home and another one will be About page. Along with this will have one not found page in case user enters some invalid page name direct on browser's URL. But before these we first go with the installation.
Without further ado install the react-router-dom package by running below command in the terminal.
npm i react-router-dom
Create a folder named "pages" and inside that add below files:
pages
|-- About.jsx
|-- Home.jsx
|-- NotFound.jsx
Make them appear as a normal component:
const Home = () => {
return (
<>Home</>
);
};
export default Home;
const About = () => {
return (
<>About</>
);
};
export default About;
const NotFound = () => {
return (
<>NotFound</>
);
};
export default NotFound;
First of all take backup of the code you have in App.jsx file, because we will be again making App.jsx blank with only header and footer left. Make your App.jsx looks like this:
import Footer from './components/Footer';
import Header from './components/Header';
function App() {
return (
<>
<Header />
<div className="container my-5">
</div>
<Footer />
</>
);
}
export default App;
Add below imports:
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
Notice, we have given alias to BrowserRouter, this is generally we do just to avoid big names.
Now, wrap every thing within Router that is present in App.jsx:
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Footer from './components/Footer';
import Header from './components/Header';
function App() {
return (
<>
<Router>
<Header />
<div className="container my-5">
</div>
<Footer />
</Router>
</>
);
}
export default App;
Configure the routes as shown below:
<div className="container my-5">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/*" element={<NotFound />} />
</Routes>
</div>
Here, individual route is added using Route component that is wrapped within the Routes component. We are using 2 attributes of Route component namely path and element. For not found pages we use wildcard path "/*".
We can now test our routes by typing the exact path in the URL area of the browser. For now, we will not be able to see much on the pages as we have nothing added to these pages; but at least we will be able to view pages.
Add content to these pages, Home, About and NotFound:
import { useState } from 'react';
import Form from './../components/Form';
import List from './../components/List';
import Empty from './../components/Empty';
const Home = () => {
const [notes, setNotes] = useState();
const getAll = notes => {
setNotes(notes);
};
const add = newNote => {
setNotes([newNote, ...notes]);
};
const remove = id => {
setNotes(notes.filter(i => i.id !== id));
};
return (
<>
<div className="row">
<div className="col">
<Form add={add} />
<List notes={notes} remove={remove} getAll={getAll} />
<Empty notes={notes} />
</div>
</div>
</>
);
};
export default Home;
import { FaHeart } from 'react-icons/fa';
import { Link } from 'react-router-dom';
const About = () => {
return (
<>
<div>
<h4 className="mb-4">
<FaHeart className="text-danger" /> About
</h4>
<p className='lead fw-semibold'>
Unleash your inner Shakespeare or just jot down your grocery list –
our notesy is here to fulfill all your note-taking fantasies.
</p>
<p>
It is like having a personal assistant who is fantastic at remembering
stuff but does not need a paycheck.
</p>
<p>
From dear diary confessions to important meeting reminders, we have
got a note template for every mood swing and milestone.
</p>
<p>
So, let your thoughts flow like a river of creativity, and let our app
be the dam that holds them all together. With us, every note is a
masterpiece waiting to happen!
</p>
<p>React: <Link to='https://react.dev/' target='_blank'>react.dev</Link>.</p>
<p>Notesy Version: <span className='badge bg-secondary'>1.0.0</span></p>
</div>
</>
);
};
export default About;
const NotFound = () => {
return (
<>
<div className="p-5 text-center bg-body-secondary rounded">
<div className='m-5'>
<h1 className="display-1 fw-bolder text-success">404</h1>
<p>The page you are looking for is no where to be found!</p>
</div>
</div>
</>
);
};
export default NotFound;
Create a Navbar component to navigate between links:
import { FaHeart, FaHome } from 'react-icons/fa';
const Navbar = () => {
return (
<>
<div className="d-flex justify-content-center mt-4">
<a href='/'>
<FaHome size={'1.2rem'} className="me-2 text-success" /> Home
</a>
<a href='/about'>
<FaHeart size={'1.2rem'} className="me-2 text-danger" /> About
</a>
</div>
</>
);
};
export default Navbar;
For any SPA, we can't use anchor tags like this, otherwise your pages will reload on these links click. A solution for this is to use Link component of react-router-dom.
import { Link } from 'react-router-dom';
<Link to={'/'}>
<FaHome size={'1.2rem'} className="me-2 text-success" /> Home
</Link>
<Link to={'/about'}>
<FaHeart size={'1.2rem'} className="me-2 text-danger" /> About
</Link>
Link component is all fine, but when you navigate from one page to another you will not be able to see the difference as in which one is active. One hurdle with Link is that you can't have CSS classes. For customizing your links you have to use NavLink componet. Replace your Link component with NavLink.
import { NavLink } from 'react-router-dom';
<NavLink to={'/'}>
<FaHome size={'1.2rem'} className="me-2 text-success" /> Home
</NavLink>
<NavLink to={'/about'}>
<FaHeart size={'1.2rem'} className="me-2 text-danger" /> About
</NavLink>
Now, add "isActiveLink" method for updating the active class to something else, by default the name of the active class is "active":
const isActiveLink = ({ isActive }) => `btn btn-light mx-1 ${isActive && 'bg-body-secondary'}`;
<NavLink to={'/'} className={isActiveLink}>
<FaHome size={'1.2rem'} className="me-2 text-success" /> Home
</NavLink>
<NavLink to={'/about'} className={isActiveLink}>
<FaHeart size={'1.2rem'} className="me-2 text-danger" /> About
</NavLink>
Here, the "isActiveLink" method receives "isActive" property that let you know about the link state, if active or inactive.
Apart from Link and NavLink if we want to navigate through code, based on condition then we have to use a hook provided by react-router-dom. For this will add some UI to Footer to navigate to About page. This time we will not use Link and NavLink, instead we will use the hook.
import { useNavigate } from 'react-router-dom';
const Footer = () => {
const navigate = useNavigate();
const handleClick = () => {
navigate('/about');
};
return (
<div className="text-center p-5 bg-light">
<button
className="btn btn-outline-dark btn-sm me-2"
onClick={handleClick}>
Notesy 1.0.0
</button>
All rights reserved © {new Date().getFullYear()}
</div>
);
};
export default Footer;
Here, we are using a hook named useNavigate, this hook gives you a method that takes one route. We are passing the "/about" path on button click.
December 31, 2020
October 19, 2020
March 02, 2022