React Router es una herramientapara crear la navegación en aplicaciones de React , y sus últimas versiones continúan mejorando la experiencia del desarrollador con nuevas funcionalidades y mejoras en el rendimiento. Desde la versión 7 (o otras versiones venideras), React Router trae características avanzadas como rutas anidadas y rutas de diseño que ayudan a construir aplicaciones web robustas y eficientes.
Características Principales en React Router 7 (o Última Versión)
Aquí hay algunas de las mejoras significativas y características introducidas en la última versión:
1. Definición Simplificada de Rutas Con APIs de Datos
Las nuevas APIs de datos, como loader
y action
, permiten fetching y modificación de datos de una manera más declarativa dentro de las rutas.
En versiones anteriores, la obtención de datos se manejaba típicamente dentro de componentes de React usando useEffect
o métodos de ciclo de vida de componentes de clase. Esto a menudo llevaba a que la lógica de obtención de datos se mezclara con la representación de la IU, lo cual podía volverse engorroso.
Ejemplo de React Router v5
import { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
function UserPage() {
const { id } = useParams();
const [userData, setUserData] = useState(null);
useEffect(() => {
fetch(`/api/users/${id}`)
.then((response) => response.json())
.then((data) => setUserData(data));
}, [id]);
return (
<div>
<h1>User: {userData?.name}</h1>
</div>
);
}
Las últimas versiones introducen APIs de Loader
, permitiendo que la obtención de datos ocurra directamente a nivel de la ruta. Esto separa preocupaciones, simplifica componentes y permite una mejor renderización concurrente.
Ejemplo de React Router v7
import { useLoaderData } from 'react-router-dom';
export async function userLoader({ params }) {
const response = await fetch(`/api/users/${params.id}`);
return response.json();
}
function UserPage() {
const userData = useLoaderData();
return (
<div>
<h1>User: {userData.name}</h1>
</div>
);
}
// Route Configuration
<Route path="/users/:id" element={<UserPage />} loader={userLoader} />
Diferencia
En React Router 7, la lógica de obtención de datos (userLoader
) está desacoplada del componente, haciendo que los componentes se centren puramente en la renderización. Este enfoque también permite pre-cargar los datos antes de que se renderice el componente, lo que conduce a una mejor experiencia de usuario y transiciones más suaves.
2. Límites de Error por Ruta
Una de las características útiles introducidas en React Router 7 (o versiones más recientes) es la capacidad de definir Límites de Error por ruta. Esto permite a los desarrolladores manejar errores a un nivel más granular. En lugar de tener un límite de error global para toda la aplicación, puedes definir límites de error específicos para rutas individuales, haciendo que la gestión de errores sea más flexible y localizada. Ahora es posible un manejo granular de errores a nivel de ruta.
En versiones anteriores, la gestión de errores era global o se manejaba a nivel de componente. Esto requería que los desarrolladores manejaran todos los errores posibles en un solo lugar o introdujeran lógica compleja en varios componentes. Como se menciona en el ejemplo a continuación, el ErrorBoundary
es global porque envuelve todo el Router
, lo que significa que capturará errores de todas las rutas dentro de la aplicación.
Ejemplo de React Router v5
function App() {
return (
<ErrorBoundary>
<Router>
<Route path="/" exact component={HomePage} />
<Route path="/about" component={AboutPage} />
</Router>
</ErrorBoundary>
);
}
React Router 7 introduce <diy9{límites de error a nivel de ruta, haciendo posible manejar errores para rutas específicas. Esto permite un control más granular sobre cómo se gestionan y muestran los errores.
Ejemplo de React Router v7
import { useRouteError } from 'react-router-dom';
function ErrorBoundary() {
const error = useRouteError();
return <div>Error: {error.message}</div>;
}
<Route path="/users/:id" element={<UserPage />} errorElement={<ErrorBoundary />} />
Diferencia
El manejo de errores en React Router 7 es más modular y localizado. Cada ruta puede definir su propio logic de manejo de errores, mejorando la experiencia del usuario cuando diferentes partes de la app fallan.
3. Mejor Manejo de Rutas de Diseño
Rutas de diseño se introducen para permitir una gestión consistente de diseños en diferentes partes de la app, reduciendo la duplicación de código.
En React Router v5, los diseños como encabezados, pie de páginas o barras laterales tenían que ser duplicados manualmente en cada ruta o componente. Esto significaba que los desarrolladores a menudo colocaban componentes de diseño (por ejemplo, Header
, Footer
) directamente dentro del componente App
o los repetían a través de diferentes manejadores de rutas, como se muestra en tu ejemplo.
Ejemplo de React Router v5
import { BrowserRouter as Router, Route } from 'react-router-dom';
import Header from './Header';
import Footer from './Footer';
import HomePage from './HomePage';
import AboutPage from './AboutPage';
function App() {
return (
<Router>
<Header />
<Route path="/" exact component={HomePage} />
<Route path="/about" component={AboutPage} />
<Footer />
</Router>
);
}
React Router 7 introduce rutas de diseño, donde puedes definir diseños compartidos que envuelven rutas anidadas, eliminando la duplicación de código y asegurando una mejor estructura.
Ejemplo de React Router v7
import { Outlet } from 'react-router-dom';
function SharedLayout() {
return (
<div>
<header>Header Content</header>
<main>
<Outlet /> {/* Nested routes will render here */}
</main>
<footer>Footer Content</footer>
</div>
);
}
// Route Configuration with Layout
<Route path="/" element={<SharedLayout />}>
<Route index element={<HomePage />} />
<Route path="about" element={<AboutPage />} />
</Route>
Diferencia
Las rutas de diseño permiten una forma limpia y reutilizable de aplicar diseños compartidos en múltiples rutas, sin repetir código. Outlet
actúa como un marcador de posición para rutas hijas, facilitando mucho la gestión de diseños.
4. Capacidad Mejorada para Rutas Anidadas
Hay formas más eficientes de manejar rutas anidadas, incluyendo la herencia de elementos de diseño y mejores estrategias de recuperación de datos.
En versiones anteriores, las rutas anidadas eran posibles, pero la configuración era más engorrosa. Había que manejar explícitamente la anidación de rutas dentro del componente padre utilizando useRouteMatch()
para obtener la ruta actual, y luego definir manualmente las rutas anidadas dentro del componente padre. Este enfoque puede volverse rápidamente engorroso, especialmente para aplicaciones complejas con múltiples capas de rutas anidadas.
React Router v5 Example
import { Route, useRouteMatch } from 'react-router-dom';
function Dashboard() {
const { path } = useRouteMatch();
return (
<div>
<h1>Dashboard</h1>
<Route path={`${path}/overview`} component={Overview} />
<Route path={`${path}/settings`} component={Settings} />
</div>
);
}
<Route path="/dashboard" component={Dashboard} />
En React Router 7, las rutas anidadas ahora se configuran de manera declarativa, directamente dentro de la configuración de la ruta, simplificando la estructura de ruteo y haciendo que el código sea más legible.
React Router v7 Example
import { Outlet } from 'react-router-dom';
function DashboardLayout() {
return (
<div>
<h1>Dashboard</h1>
<Outlet /> {/* Nested routes will render here */}
</div>
);
}
// Route Configuration
<Route path="/dashboard" element={<DashboardLayout />}>
<Route path="overview" element={<Overview />} />
<Route path="settings" element={<Settings />} />
</Route>
Difference
En React Router 7, las rutas anidadas son más fáciles de gestionar porque se definen en el nivel de configuración de la ruta utilizando el componente Outlet
. Esta estructura promueve una clara separación entre el diseño y el contenido.
5. Integración Mejorada de Suspense
Ahora, se encuentra un mejor soporte para el React 18’s Suspense
y renderizado concurrente para experiencias de carga más suaves.
En versiones anteriores, el suspense solo estaba soportado para componentes lazy-loaded en versiones anteriores, limitando su utilidad para escenarios de fetching de datos complejos.
React Router v5 Example
import React, { Suspense, lazy } from 'react';
const HomePage = lazy(() => import('./HomePage'));
<Suspense fallback={<div>Loading</div>}>
<Route path="/" component={HomePage} />
</Suspense>
React Router 7 integra Suspense
con su Loader y Action APIs, permitiendo una carga de datos más suave y concurrente con un mínimo esfuerzo.
React Router v7 Example
import { Suspense } from 'react';
import { Route, Routes } from 'react-router-dom';
function App() {
return (
<Suspense fallback={<div>Loading</div>}>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
</Routes>
</Suspense>
);
}
Diferencia
React Router 7 aprovecha Suspense
tanto para componentes cargados perezosamente como para la carga de datos, permitiendo transiciones más suaves y una interfaz de usuario más responsiva.
Conclusión
React Router 7 (o la versión más reciente) mejora significativamente el enrutamiento en aplicaciones de React al introducir varias características poderosas. Las nuevas Loader y Action APIs permiten una carga de datos declarativa, separando la lógica de datos de los componentes para obtener un código más limpio. Layout Routes simplifican la gestión de layouts compartidos, reduciendo la redundancia. Nested routes son más eficientes e intuitivos, permitiendo una estructura más clara. Además, límites de error por ruta proporcionan un manejo de errores más granular, mejorando la fiabilidad. La integración completa con React Suspense
respalda una carga de datos más suave y una mejor experiencia de usuario. Juntas, estas mejoras simplifican el desarrollo de aplicaciones de React complejas, escalables y de alto rendimiento, haciendo de React Router 7 una actualización significativa respecto a versiones anteriores.
Source:
https://dzone.com/articles/why-react-router-7-is-a-game-changer-for-react-devs