Si estan trabajando con react-router-dom 7 se debe hacer lo siguiente para que no se acumulen las rutas del dasboard
<Route path="/dashboard" element={<Dashboard />}>
Las rutas anidadas en React Router te permiten organizar vistas internas dentro de un componente padre, mientras que el lazy loading con Suspense mejora el rendimiento al cargar componentes solo cuando se necesitan. Esta combinación es clave para cualquier desarrollador frontend que quiera apps más rápidas y mejor estructuradas.
¿Cómo se crean rutas anidadas en React Router?
La idea es montar un componente padre, en este caso Dashboard, y dejar que dentro vivan vistas hijas como Overview y Settings. Para que React Router entienda que hay subrutas, le agregas un asterisco al path del padre.
En la sección de rutas defines algo así: la ruta dashboard/* apunta al componente Dashboard, y dentro de esa ruta declaras las hijas con paths relativos como overview y settings. Nada de slash al inicio en las hijas, solo el nombre.
¿Para qué sirve el asterisco en una ruta de React Router? Le indica al router que esa ruta acepta subrutas anidadas. Todo lo que venga después de
dashboard/será gestionado por las rutas hijas que definas dentro.
¿Cómo se navega entre rutas anidadas?
Dentro del componente Dashboard agregas una lista de enlaces usando el componente Link importado desde react-router-dom. Los to de esos enlaces ya no llevan slash inicial, basta con escribir overview o settings porque son rutas relativas al padre.
Al hacer clic, la URL en el navegador cambia a /dashboard/overview o /dashboard/settings, confirmando que el anidamiento funciona.
¿Qué hace el componente Outlet en React Router?
Aquí viene lo interesante: aunque definas las rutas hijas, no se renderizan solas dentro del padre. Necesitas decirle a React dónde pintarlas. Para eso existe Outlet.
Outlet es un componente de react-router-dom que actúa como el espacio reservado donde se monta la vista hija activa. Lo importas y lo colocas dentro del JSX de Dashboard, en el lugar exacto donde quieres que aparezca Overview o Settings.
¿Qué pasa si no uso Outlet en una ruta padre? Las rutas hijas existirán en la URL pero no se mostrarán en pantalla.
Outletes el encargado de renderizar el componente hijo activo dentro del padre.
Sin Outlet, ves el contenido base del Dashboard pero las vistas anidadas no aparecen aunque la URL sí cambie.
¿Cómo aplicar lazy loading con Suspense en React?
Cuando una vista es pesada, cargarla solo cuando el usuario la solicita evita ralentizar el render inicial. Para eso usas Suspense, un componente que viene directamente de React.
La importación se ve así: import React, { Suspense } from 'react'. Luego, en la definición de la ruta que quieres cargar de forma diferida —por ejemplo, Settings— envuelves el componente con Suspense dentro del element de la ruta.
¿Qué es el fallback en Suspense y por qué es obligatorio?
Suspense requiere una prop llamada fallback. Esa prop define qué se muestra mientras el componente real termina de cargar.
Puedes pasarle desde un texto simple hasta un shimmer o spinner. Ejemplos comunes:
div con el texto Loading....El fallback se renderiza primero y, cuando el componente está listo, se reemplaza por la vista definitiva. Si la página es liviana, el cambio es casi imperceptible; si es pesada, el usuario ve el estado de carga sin pantalla en blanco.
¿Cómo queda la estructura final del Dashboard con rutas anidadas y lazy loading?
La receta combina tres piezas que trabajan juntas:
dashboard/* que apunta al componente Dashboard.overview y settings declaradas dentro de la ruta padre, con paths relativos sin slash.Dashboard con un menú de Link y un Outlet para renderizar la vista hija activa.Suspense envolviendo los componentes que quieras cargar de forma lazy, con un fallback definido.Con esta estructura, navegar a /dashboard muestra el shell del dashboard. Al hacer clic en Overview, la URL pasa a /dashboard/overview y el Outlet renderiza esa vista. Lo mismo con Settings, que además se carga de forma diferida gracias a Suspense.
¿Ya probaste combinar Outlet con Suspense en tus proyectos? Cuéntame en los comentarios qué fallback usas y si prefieres un texto simple o un skeleton más elaborado.
Las rutas anidadas en React Router te permiten organizar vistas internas dentro de un componente padre, mientras que el lazy loading con Suspense mejora el rendimiento al cargar componentes solo cuando se necesitan. Esta combinación es clave para cualquier desarrollador frontend que quiera apps más rápidas y mejor estructuradas.
La idea es montar un componente padre, en este caso Dashboard, y dejar que dentro vivan vistas hijas como Overview y Settings. Para que React Router entienda que hay subrutas, le agregas un asterisco al path del padre.
En la sección de rutas defines algo así: la ruta dashboard/* apunta al componente Dashboard, y dentro de esa ruta declaras las hijas con paths relativos como overview y settings. Nada de slash al inicio en las hijas, solo el nombre.
¿Para qué sirve el asterisco en una ruta de React Router? Le indica al router que esa ruta acepta subrutas anidadas. Todo lo que venga después de
dashboard/será gestionado por las rutas hijas que definas dentro.
Dentro del componente Dashboard agregas una lista de enlaces usando el componente Link importado desde react-router-dom. Los to de esos enlaces ya no llevan slash inicial, basta con escribir overview o settings porque son rutas relativas al padre.
Al hacer clic, la URL en el navegador cambia a /dashboard/overview o /dashboard/settings, confirmando que el anidamiento funciona.
Aquí viene lo interesante: aunque definas las rutas hijas, no se renderizan solas dentro del padre. Necesitas decirle a React dónde pintarlas. Para eso existe Outlet.
Outlet es un componente de react-router-dom que actúa como el espacio reservado donde se monta la vista hija activa. Lo importas y lo colocas dentro del JSX de Dashboard, en el lugar exacto donde quieres que aparezca Overview o Settings.
¿Qué pasa si no uso Outlet en una ruta padre? Las rutas hijas existirán en la URL pero no se mostrarán en pantalla.
Outletes el encargado de renderizar el componente hijo activo dentro del padre.
Sin Outlet, ves el contenido base del Dashboard pero las vistas anidadas no aparecen aunque la URL sí cambie.
Cuando una vista es pesada, cargarla solo cuando el usuario la solicita evita ralentizar el render inicial. Para eso usas Suspense, un componente que viene directamente de React.
La importación se ve así: import React, { Suspense } from 'react'. Luego, en la definición de la ruta que quieres cargar de forma diferida —por ejemplo, Settings— envuelves el componente con Suspense dentro del element de la ruta.
Suspense requiere una prop llamada fallback. Esa prop define qué se muestra mientras el componente real termina de cargar.
Puedes pasarle desde un texto simple hasta un shimmer o spinner. Ejemplos comunes:
div con el texto Loading....El fallback se renderiza primero y, cuando el componente está listo, se reemplaza por la vista definitiva. Si la página es liviana, el cambio es casi imperceptible; si es pesada, el usuario ve el estado de carga sin pantalla en blanco.
La receta combina tres piezas que trabajan juntas:
dashboard/* que apunta al componente Dashboard.overview y settings declaradas dentro de la ruta padre, con paths relativos sin slash.Dashboard con un menú de Link y un Outlet para renderizar la vista hija activa.Suspense envolviendo los componentes que quieras cargar de forma lazy, con un fallback definido.Con esta estructura, navegar a /dashboard muestra el shell del dashboard. Al hacer clic en Overview, la URL pasa a /dashboard/overview y el Outlet renderiza esa vista. Lo mismo con Settings, que además se carga de forma diferida gracias a Suspense.
¿Ya probaste combinar Outlet con Suspense en tus proyectos? Cuéntame en los comentarios qué fallback usas y si prefieres un texto simple o un skeleton más elaborado.
Si estan trabajando con react-router-dom 7 se debe hacer lo siguiente para que no se acumulen las rutas del dasboard
<Route path="/dashboard" element={<Dashboard />}>
En mi caso poniendo '*' a la ruta principal lo que pasaba era que en la url la ruta se iba acumulando, es decir, /dashboard/overview/settings y asi por mas que diera click en el link, por lo que quitando el '*' me salio igual que a la teffcode
Para el correcto uso de el Suspense, falto hacer el import de el componente Settings usando la funcion lazy de React.
const Settings = lazy(() => import('./components/Settings')
Lazy Loading en React se utiliza para cargar componentes de forma diferida, mejorando el rendimiento de la aplicación. Al emplear React.lazy(), los componentes se cargan solo cuando son necesarios, en lugar de cargarlos todos al principio, lo que reduce el tiempo de carga inicial y mejora la experiencia del usuario. Se combina con Suspense para mostrar un fallback, como un mensaje de carga, mientras el componente se está descargando. Esta técnica es especialmente útil en aplicaciones grandes con muchas rutas y componentes.
Para las versiones: "dependencies": {
"react": "19.2.4",
"react-dom": "19.2.4",
"react-router-dom": "7.13.0"
},
Para que no se repitan las rutas, las tengo como:
<Routes>
<Route path='/' element={<Home />}></Route>
<Route path='/about' element={<About />}></Route>
<Route path='/product/:id' element={<Product />}></Route>
<Route path='dashboard' element={<Dashboard />}>
<Route path='overview' element={<Overview />}></Route>
<Route path='settings' element={<Settings />}></Route>
</Route>
</Routes>
Cesidio Antonio Di Benedetto Carri
Armando Salamanca Ayon
Jorge Uriel Chavira López
Salomon Moreno
Abinadi Contreras
Mariana Valencia Gallego
Juan Camilo Noreña López
David Rangel
Si estan trabajando con react-router-dom 7 se debe hacer lo siguiente para que no se acumulen las rutas del dasboard
<Route path="/dashboard" element={<Dashboard />}>
En mi caso poniendo '*' a la ruta principal lo que pasaba era que en la url la ruta se iba acumulando, es decir, /dashboard/overview/settings y asi por mas que diera click en el link, por lo que quitando el '*' me salio igual que a la teffcode
Según Cesidio, es por la version de <Route path="/dashboard" element={<Dashboard />}>react-router-dom. Lo que puedes hacer es eliminar el "/*" de la ruta y debería de funcionar
<Route path="/dashboard" element={<Dashboard />}>
Para el correcto uso de el Suspense, falto hacer el import de el componente Settings usando la funcion lazy de React.
const Settings = lazy(() => import('./components/Settings')
sin eso no funciona?
Abinadi, si no haces el import lazy, vas a ver todo normal, no se va a romper la app. Sin embargo lo que se busca con el lazy y el suspense es que la app sea lo menos pesada en la carga inicial como sea posible, solo descargando el js de las rutas secundarias si el usuario clickea en ellas.
Si usas bien el lazy y el suspense e inspeccionas en el Network seleccionando "All" en los filtros, vas a ver que cuando recargas la app se descargan todos los archivos de las rutas menos el de Settings. Solo cuando entras a la ruta de Settings es que ves que este se descarga
Lazy Loading en React se utiliza para cargar componentes de forma diferida, mejorando el rendimiento de la aplicación. Al emplear React.lazy(), los componentes se cargan solo cuando son necesarios, en lugar de cargarlos todos al principio, lo que reduce el tiempo de carga inicial y mejora la experiencia del usuario. Se combina con Suspense para mostrar un fallback, como un mensaje de carga, mientras el componente se está descargando. Esta técnica es especialmente útil en aplicaciones grandes con muchas rutas y componentes.
Para las versiones: "dependencies": {
"react": "19.2.4",
"react-dom": "19.2.4",
"react-router-dom": "7.13.0"
},
Para que no se repitan las rutas, las tengo como:
<Routes> <Route path='/' element={<Home />}></Route> <Route path='/about' element={<About />}></Route> <Route path='/product/:id' element={<Product />}></Route> <Route path='dashboard' element={<Dashboard />}> <Route path='overview' element={<Overview />}></Route> <Route path='settings' element={<Settings />}></Route> </Route> </Routes>