Understanding children vs element in React Router’s createBrowserRouter (with Protected Routes)
When working with React Router v6+, you’ve probably noticed two key props inside createBrowserRouter:
-
element -
children
At first glance, they look similar — but they serve very different purposes. Understanding this distinction is essential for building scalable routing systems, especially when you add layouts and protected routes (auth/admin).
In this blog, we’ll break down the difference, show real-world examples, and explain how element and children combine to create a flexible router tree.
Quick Refresher: createBrowserRouter
Here’s a simplified version of your router setup:
import { createBrowserRouter, Navigate } from 'react-router';
import { ShopLayout } from './shop/layouts/ShopLayout';
import { HomePage } from './shop/pages/home/HomePage';
import { ProductPage } from './shop/pages/product/ProductPage';
import { GenderPage } from './shop/pages/gender/GenderPage';
export const appRouter = createBrowserRouter([
{
path: '/',
element: <ShopLayout />, // ✅ Layout (element)
children: [
{
index: true,
element: <HomePage />, // ✅ Nested route (child)
},
{
path: 'product/:idSlug',
element: <ProductPage />,
},
{
path: 'gender/:gender',
element: <GenderPage />,
},
],
},
{
path: '*',
element: <Navigate to="/" />,
},
]);
element → Defines what gets rendered at that route
-
elementis the React node/component that should be rendered when the URL matches the route’spath. - Think of it as the container or layout for that route.
👉 Example:
{
path: '/auth',
element: <AuthLayout />, // Renders the Auth layout wrapper
}
If the user navigates to /auth, React Router renders <AuthLayout />.
children → Defines nested routes inside the layout
-
childrenrepresent nested routes that live inside the parent’selement. - They are rendered inside the parent’s
<Outlet />.
👉 Example:
{
path: '/auth',
element: <AuthLayout />,
children: [
{
index: true,
element: <Navigate to="/auth/login" />,
},
{
path: 'login',
element: <LoginPage />,
},
{
path: 'register',
element: <RegisterPage />,
},
],
}
Here:
-
/auth/login→ Renders<LoginPage />inside<AuthLayout />. -
/auth/register→ Renders<RegisterPage />inside<AuthLayout />.
This is possible because <AuthLayout /> likely uses <Outlet /> somewhere inside.
Protected Routes with element
You can wrap layouts or pages inside route guards (like AdminRoute or NotAuthenticatedRoute).
👉 Example:
{
path: '/admin',
element: (
<AdminRoute>
<AdminLayout />
</AdminRoute>
),
children: [
{ index: true, element: <DashboardPage /> },
{ path: 'products', element: <AdminProductsPage /> },
{ path: 'products/:id', element: <AdminProductPage /> },
],
}
What’s happening here?
-
element=<AdminRoute><AdminLayout /></AdminRoute> - That means before rendering
<AdminLayout />, theAdminRoutechecks if the user is authenticated and authorized. - If yes → renders the layout and its children.
- If no → redirects to login or shows an error page.
Visual Mental Model
Think of it like this:
/auth
├── element: <AuthLayout />
└── children:
• /login → <LoginPage />
• /register → <RegisterPage />
/admin
├── element: <AdminRoute><AdminLayout /></AdminRoute>
└── children:
• / → <DashboardPage />
• /products → <AdminProductsPage />
• /products/:id → <AdminProductPage />
-
element= the wrapping layout/guard -
children= the actual content pages, injected via<Outlet />
Pro Tips 🚀
✅ Use element for:
- Layouts (
ShopLayout,AuthLayout,AdminLayout) - Route guards (
AdminRoute,NotAuthenticatedRoute)
✅ Use children for:
- Nested routes rendered inside a parent layout.
- Structuring multi-level apps (shop, auth, admin, etc.).
✅ Always add an index: true child for default pages.
✅ Use <Navigate /> for redirects in element.
Conclusion
The difference between element vs children is subtle but powerful:
-
element= the wrapper or layout (what renders immediately at that path). -
children= the nested routes inside that layout (rendered through<Outlet />).
When combined with ProtectedRoutes, this pattern gives you a scalable and secure routing architecture for modern React apps.
Next time you’re structuring routes, ask yourself:
👉 Is this a wrapper/layout/guard? → Use element.
👉 Is this a page inside a layout? → Use children.
✍️ Written by: Cristian Sifuentes — Full-stack developer & AI/JS enthusiast, passionate about React, TypeScript, and scalable architectures.
✅ Tags: #react #frontend #routing #programming

Top comments (0)