Check your version
This post assumes you're using React Router v6. If not, find your version below.React Router has gone through a few different iterations over the years. Though the current API (v6) takes a declarative, component-based, <Route />
as you go approach – this hasn't always been the case.
In fact, in the first versions of React Router (v1-v3), instead of composing your Route
s as you do now throughout your application, you'd declare them up front in a central route config then pass that to ReactDOM.render
.
const routes = (<Router><Route path="/" component={Main}><IndexRoute component={Home} /><Route path="battle" component={ConfirmBattle} /><Route path="results" component={Results} /></Route></Router>);ReactDOM.render(routes, document.getElementById("app"));
Though React Router has moved away from this central route config approach, it still had its benefits. Namely, when server rendering or doing static analysis.
The good news is, as of v6, React Router now comes with a useRoutes
Hook that makes collocating your routes into a central route config not only possible, but simple with a first class API as well.
Say we had the following paths in our application.
//invoices:idpendingcomplete/users:idsettings
Typically if you wanted to map those paths to different React components, you'd render something like this.
return (<Routes><Route path="/" element={<Home />} /><Route path="/invoices" element={<Invoices />}><Route path=":id" element={<Invoice />} /><Route path="pending" element={<Pending />} /><Route path="complete" element={<Complete />} /></Route><Route path="/users/*" element={<Users />} /></Routes>);
Notice that we're rendering the nested routes for invoices/:id
, invoices/pending
, and invoices/complete
here but the nested routes for /users/:id
and /users/settings
are going to be rendered inside the Users
component.
Now what useRoutes
allows us to do is, instead of declaring our routes using React elements, we can do it using JavaScript objects all in one location.
useRoutes
takes in an array of JavaScript objects which represent the routes in your application. Similar to the React element API with <Route>
, each route has a path
, element
, and an optional children
property.
import { useRoutes } from "react-router-dom";const routes = useRoutes([{ path: "/", element: <Home /> },{path: "/invoices",element: <Invoices />,children: [{ path: ":id", element: <Invoice /> },{ path: "/pending", element: <Pending /> },{ path: "/complete", element: <Complete /> },],},{path: "/users",element: <Users />,children: [{ path: ":id", element: <Profile /> },{ path: "/settings", element: <Settings /> },],},]);export default function App() {return (<div><Navbar />{routes}</div>);}
What makes useRoutes
even more interesting is how React Router uses it internally. In fact, when you use the React element API to create your Routes
, it's really just a wrapper around useRoutes
.