Last updated: Apr 6, 2024
Reading timeยท3 min
The error "useRoutes() may be used only in the context of a Router component"
occurs when we try to use the useRoutes
hook outside of the Router context in
React Router.
To solve the error, use the useRoutes
hook only within the Router context.
Here is an example of wrapping your React app in a Router
in your index.js
file.
import {createRoot} from 'react-dom/client'; import App from './App'; import {BrowserRouter as Router} from 'react-router-dom'; const rootElement = document.getElementById('root'); const root = createRoot(rootElement); // ๐๏ธ Wrap App in Router root.render( <Router> <App /> </Router> );
Now you can use the useRoutes
hook in your App.js
file.
import React from 'react'; import { useRoutes } from 'react-router-dom'; export default function App() { let element = useRoutes([ {path: '/', element: <Home />}, {path: '/about', element: <About />}, ]); return element; } function Home() { return <h2>Home</h2>; } function About() { return <h2>About</h2>; }
The error occurs because the useRoutes
hook makes use of the context that the
Router
component provides, so it has to be nested inside of a Router
.
Router
component is in your index.js
file because that's the entry point of your React application.Once your entire app is wrapped with a Router
component, you can use any of
the hooks from the React Router package anywhere in your components.
The useRoutes
hook is the functional equivalent of Routes
, so you can also
use a component instead of objects to define your routes.
import React from 'react'; import {BrowserRouter as Router, Route, Link, Routes} from 'react-router-dom'; export default function App() { return ( <Router> <div> <nav> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/about">About</Link> </li> </ul> </nav> {/* ๐๏ธ Wrap your Route components in a Routes component */} <Routes> <Route path="/about" element={<About />} /> <Route path="/" element={<Home />} /> </Routes> </div> </Router> ); } function Home() { return <h2>Home</h2>; } function About() { return <h2>About</h2>; }
React router uses a simplified path format where <Route path>
has 2 kinds of
placeholders:
:id
params*
wildcardsThe *
wildcard syntax can only be used at the end of a path.
import React from 'react'; import {BrowserRouter as Router, Route, Link, Routes} from 'react-router-dom'; import {useParams} from 'react-router-dom'; export default function App() { return ( <Router> <div> <nav> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/about">About</Link> </li> <li> {/* ๐๏ธ link to dynamic path */} <Link to="/users/4200">Users</Link> </li> <li> {/* ๐๏ธ link to catch all route */} <Link to="/does-not-exist">Catch all route</Link> </li> </ul> </nav> {/* ๐๏ธ Wrap your Route components in a Routes component */} <Routes> <Route path="/about" element={<About />} /> {/* ๐๏ธ handle dynamic path */} <Route path="/users/:userId" element={<Users />} /> <Route path="/" element={<Home />} /> {/* ๐๏ธ only match this when no other routes match */} <Route path="*" element={ <div> <h2>404 Page not found etc</h2> </div> } /> </Routes> </div> </Router> ); } function Home() { return <h2>Home</h2>; } function About() { return <h2>About</h2>; } function Users() { const params = useParams(); return <h2>Users: {params.userId}</h2>; }
The route <Route path="/users/:userId" element={<Users />} />
uses a dynamic
userId
parameter, which we can access by using the useParams
hook.
The route would match anything after /users/
, e.g. /users/123
or
/users/asdf
.
The route that has a path equal to *
serves as a catch-all route. It only
matches when no other routes do.
For more examples, refer to the official docs page of React Router.
I've also written a detailed guide on how to handle 404 page not found in React Router.