React-router
Introduction
This page is about routering with React.
Setup
Install package for Router
npm i react-router-dom
Add BrowserRouter to Index.js
...
import { BrowserRouter } from 'react-router-dom';
...
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root')
);
Add Routes to App.js
We need to a routes to the the router we support.
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';
import Explore from './components/Explore';
import Home from './components/Home';
import Messages from './components/Messages';
import Profile from './components/Profile';
function App() {
return (
<Router>
<div>
<h2>Welcome to React Router Tutorial</h2>
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<ul className="navbar-nav mr-auto">
<li><Link to={'/'} className="nav-link"> Home </Link></li>
<li><Link to={'/explore'} className="nav-link">Explore</Link></li>
<li><Link to={'/messages'} className="nav-link">Messages</Link></li>
<li><Link to={'/profile'} className="nav-link">Profile</Link></li>
</ul>
</nav>
<hr />
<Switch>
<Route exact path='/' component={Home} />
<Route path='/explore' component={Explore} />
<Route path='/messages' component={Messages} />
<Route path='/profile' component={Profile} />
</Switch>
</div>
</Router>
);
}
export default App;
Create Pages
Functional Based
Create a component for each page
import React from 'react'
const Home = () => {
return (
<div>
<h2>Home</h2>
</div>
);
};
export default Home
Class Component Based
Create a component for each page
import React, { Component } from 'react';
class Profile extends Component {
render() {
return (
<div>
<h2>Profile</h2>
</div>
);
}
}
export default Profile;
Component Based
This allows us to work with the activeClassName and exact to highlight the list which is active.
<Router>
<Nav authenticated={!defaultToSignIn} />
<hr />
<Switch>
<Route path="/" component={Home} exact />
<Route path="/auth/login" component={Login} />
<Route path="/auth/Register" component={Register} />
<Route path="/auth/logout" component={Logout} />
</Switch>
</Router>
And for some of the NavLink routes
<li className="nav-item">
<NavLink
to="/home"
aria-current="page"
className="nav-link"
exact
>
Home
</NavLink>
</li>
</ul>
<ul className="navbar-nav ms-auto mb-2 mb-lg-0">
<li className="nav-item">
<NavLink to="/explore" aria-current="page" className="nav-link">
Explore
</NavLink>
</li>
<li className="nav-item">
<NavLink to="/messages" aria-current="page" className="nav-link">
Messages
</NavLink>
</li>
Prompt Component
We can prevent leaving of a page with the Prompt component. For example.
...
return (
<div className="Login">
{error && <p intent="danger">{error}</p>}
<Prompt
when={!usernameValid || !passwordValid}
message="Leaving page will loose your data"
/>
<Form onSubmit={handleSubmit} className="row g-3 needs-validation">
<div>
<div className="col-md-4">
<Form.Group size="lg" controlId="username">
<Form.Label>Username</Form.Label>
<Form.Control
...
Adding a 404 Page
To implement this we just create a route with no path and a component
<Router>
<Nav authenticated={!defaultToSignIn} />
<hr />
<Switch>
<Route
exact
path="/"
render={() =>
defaultToSignIn ? (
<Redirect to="/auth/login" />
) : (
<Redirect to="/home" />
)
}
/>
<ProtectedRoute path="/" component={Home} exact />
<ProtectedRoute path="/explore" component={Explore} />
<ProtectedRoute path="/messages" component={Messages} />
<ProtectedRoute path="/profile" component={Profile} />
<Route path="/auth/login" component={Login} />
<Route path="/auth/Register" component={Register} />
<Route path="/auth/logout" component={Logout} />
<Route component={PageNotFound} />
</Switch>
</Router>
Rendering Component with Parameters
When you need to add props to the component to render we use the render property which takes a function as an argument and should return the Component for the page.
Router
<Router>
<Switch>
<Route path="/auth/logout" component={Logout} />
<Route path="/compwithprops" render={() => {
return <CompWithProps prop1="#ff0000" prop2='Red'/>
}) />
<Route component={PageNotFound} />
</Switch>
Component
For the component we need to wrap it with withRouter in a HOC.
import React from "react";
const CompWithProps = ({prop1,prop2}) => (
<div>
..
</div>
);
export default CompWithProps;
CompWithProps.proptypes = {
prop1: PropTypes.string.isRequired,
prop2: PropTypes.string.isRequired,
}
Router Children Component
All router children components get the following props.
- match Exact Match, Params, Path and matching Url
- location Key, path name and search
- history This is the browser history
Transitions
You need to provide a class prefix in this case trans.
import {TransitionGroup, CSSTransition} from 'react-transition-group'
<TransactionGroup>
<CSSTransition key={location.key} classNames={'trans'} timeout={1000}>
<Switch location={location}>
<Route path={`${match.url}`} component={LoremNumber} exact/>
<Route path={`${match.url}/:id`} component={LoremNumber} exact/>
</Switch>
</TransactionGroup>
And the CSS
.trans-enter {
opacity: 0;
z-index: 1;
}
.trans-exit {
display: none
}
.trans-enter.trans-enter-active {
opacity: 1;
transition: opacity 1000ms ease-in;
}