React Router 5 embraces the power of hooks and has introduces four different hooks to help with your routing.
But before we look at hooks themselves, we have to look at a new pattern that the Route component exposes and how this changes things.
Before:
// When you wanted to render the route and get router props for component
<Route path="/" component={Home} />
// Or when you wanted to pass extra props
<Route path="/" render={({ match }) => <Profile match={match} mine={true} />}>
When using the component syntax, route props (match, location and history) are implicitly being passed on to the component. But it has to be changed to render once you have extra props to pass to the component. Note that adding a function to the component syntax would lead to the component re-mounting on every render.
After:
<Route path="/">
  <Home />
</Route>
Note that there is no implicit passing of any props to the Home component. But without changing anything with the Route itself, you can add any extra props to the Home component. You can no longer make the mistake of re-mounting the component on every render and that's the best kind of APIs.
But now that implicit passing of route props is not there, how do we access match, history or location? Do we have to wrap all components with withRouter? That is where the hooks steps in.
Note that hooks were introduced in 16.8 version of React, so you need to be above that version to use them.
useHistoryhistory prop in React Routerpush, replace etcimport { useHistory } from "react-router-dom";
function Home() {
  const history = useHistory();
  return <button onClick={() => history.push("/profile")}>Profile</button>;
}
useLocationlocation prop in React Routerwindow.location in the browser itself, but this is accessible everywhere as it represents the Router state and location.import { useLocation } from "react-router-dom";
function Profile() {
  const location = useLocation();
  useEffect(() => {
    const currentPath = location.pathname;
    const searchParams = new URLSearchParams(location.search);
  }, [location]);
  return <p>Profile</p>;
}
Since location property is immutable, the
useEffectwill call the function everytime the route changes, making it perfect to operate on search parameters or current path.
useParamsmatch.paramsimport { useParams, Route } from "react-router-dom";
function Profile() {
  const { name } = useParams();
  return <p>{name}'s Profile</p>;
}
function Dashboard() {
  return (
    <>
      <nav>
        <Link to={`/profile/ann`}>Ann's Profile</Link>
      </nav>
      <main>
        <Route path="/profile/:name">
          <Profile />
        </Route>
      </main>
    </>
  );
}
useRouteMatchimport { useRouteMatch, Route } from "react-router-dom";
function Auth() {
  const match = useRouteMatch();
  return (
    <>
      <Route path={`${match.url}/login`}>
        <Login />
      </Route>
      <Route path={`${match.url}/register`}>
        <Register />
      </Route>
    </>
  );
}
You can also use useRouteMatch to access a match without rendering a Route, this is done by passing it the location argument.
For example, consider that you need your own profile to be rendered at /profile and somebody else's profile if the URL contains the name of the person /profile/dan or /profile/ann. Without using the hook, you would either write a Switch and list down both routes and customise them with props, now using the hook:
import {
  Route,
  BrowserRouter as Router,
  Link,
  useRouteMatch,
} from "react-router-dom";
function Profile() {
  const match = useRouteMatch("/profile/:name");
  return match ? <p>{match.params.name}'s Profile</p> : <p>My own profile</p>;
}
export default function App() {
  return (
    <Router>
      <nav>
        <Link to="/profile">My Profile</Link>
        <br />
        <Link to={`/profile/ann`}>Ann's Profile</Link>
      </nav>
      <Route path="/profile">
        <Profile />
      </Route>
    </Router>
  );
}
You can also use all the props on
Routelikeexactorsensitiveas an object withuseRouteMatch.
Using the hooks and the technique we mentioned in the beginning with Route would make it much easier to upgrade to new versions of React Router.