I'm trying to organize my App.jsx
file, although I've noticed that it is getting bigger and bigger considering the number of routes.
How is it possible to reduce the length of the file instead of adding all the contents inside?
Here is an example:
function App() {
const isAuthenticated = userTokenStore((state) => state.isLoggedIn);
return (
<Router>
<Routes>
<Route path="/" element={<Landing />} />
<Route path="/support" element={<Support />} />
<Route path="/apply" element={<Apply />} />
<Route path="/about" element={<About />} />
<Route path="/login" element={<Login />} />
<Route
path="/admin/dashboard"
element={
<PrivateRoute isAuthenticated={isAuthenticated}>
<AdminLayout>
<Dashboard />
</AdminLayout>
</PrivateRoute>
}
/>
<Route
path="/admin/tickets"
element={
<PrivateRoute isAuthenticated={isAuthenticated}>
<AdminLayout>
<Tickets />
</AdminLayout>
</PrivateRoute>
}
/>
<Route
path="/admin/orders"
element={
<PrivateRoute isAuthenticated={isAuthenticated}>
<AdminLayout>
<Orders />
</AdminLayout>
</PrivateRoute>
}
/>
</Routes>
</Router>
);
}
export default App;
What I'd like to do is to create a PublicRoutes.jsx
file, and an AdminRoutes.jsx
file, and make use of those on the main, so it would look like this:
function App() {
const isAuthenticated = userTokenStore((state) => state.isLoggedIn);
return (
<Router>
<Routes>
<PublicRoutes />
<AdminRoutes />
</Routes>
</Router>
);
}
export default App;
Is it possible? I've tried it, but react-router-dom
is strictly telling me that I cannot add anything other than <Route>
components inside <Router>
.
Yes, you can certainly split the routes up. Instead of rendering nested routes you would now render descendent routes and the parent route in App
would render a path with a trailing "*"
wildcard matcher, or splat, to allow descendent routes to also be matched and rendered.
const PublicRoutes = () => (
<Routes>
<Route path="/" element={<Landing />} />
<Route path="/support" element={<Support />} />
<Route path="/apply" element={<Apply />} />
<Route path="/about" element={<About />} />
<Route path="/login" element={<Login />} />
</Routes>
);
const AdminRoutes = () => (
<Routes>
<Route element={<AdminLayout />}>
<Route element={<PrivateRoute />}>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/tickets" element={<Tickets />} />
<Route path="/orders" element={<Orders />} />
</Route>
</Route>
</Routes>
);
function App() {
return (
<Router>
<Routes>
<Route path="*" element={<PublicRoutes />} />
<Route path="/admin/*" element={<AdminRoutes />} />
</Routes>
</Router>
);
}
In the above, the PrivateRoute
and AdminLayout
components have been converted to layout route components, e.g. they render an Outlet
component instead of a children
prop. This is another way to reduce the amount of code you write, e.g. it helps make your code more DRY.
const PrivateRoute = () => {
const isAuthenticated = userTokenStore((state) => state.isLoggedIn);
return isAuthenticated
? <Outlet />
: <Navigate to="/login" replace />;
};
const AdminLayout = () => {
...
return (
...
<Outlet />
...
);
};
For more information:
In terms of code reduction, if you made just the layout route changes then your original code could look like the following:
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Landing />} />
<Route path="/support" element={<Support />} />
<Route path="/apply" element={<Apply />} />
<Route path="/about" element={<About />} />
<Route path="/login" element={<Login />} />
<Route path="/admin" element={<AdminLayout />}>
<Route element={<PrivateRoute />}>
<Route path="dashboard" element={<Dashboard />} />
<Route path="tickets" element={<Tickets />} />
<Route path="orders" element={<Orders />} />
</Route>
</Route>
</Routes>
</Router>
);
}