O React Router é uma ferramenta essencial para criar navegação em aplicações React, e suas últimas versões continuam a melhorar a experiência do desenvolvedor com novas funcionalidades e melhorias de desempenho. A partir da versão 7 (ou outras versões futuras), o React Router traz recursos avançados como rotas aninhadas e rotas de layout que ajudam a construir aplicações web robustas e eficientes.
Principais Novas Funcionalidades no React Router 7 (ou Versão Mais Recente)
Aqui estão algumas das melhorias e funcionalidades significativas introduzidas na versão mais recente:
1. Definição Simplificada de Rotas Com APIs de Dados
Novas APIs de dados, como loader
e action
, permitem buscar e modificar dados de uma maneira mais declarativa dentro das rotas.
Nas versões antigas, a busca de dados era tipicamente tratada dentro de componentes React usando useEffect
ou métodos de ciclo de vida de componentes de classe. Isso frequentemente levava a lógicas de busca de dados misturadas com a renderização da UI, o que podia se tornar incômodo.
Exemplo 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>
);
}
As versões mais recentes introduzem APIs de Loader
, permitindo que a busca de dados ocorra diretamente no nível da rota. Isso separa preocupações, simplifica componentes e permite uma renderização concorrente melhor.
Exemplo 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} />
Diferença
No React Router 7, a lógica de busca de dados (userLoader
) está desacoplada do componente, fazendo com que os componentes fiquem puramente focados em renderização. Esta abordagem também permite que os dados sejam pré-buscados antes da renderização do componente, levando a uma melhor experiência do usuário e transições mais suaves.
2. Limites de Erro por Rota
Uma das características úteis introduzidas no React Router 7 (ou versões mais recentes) é a capacidade de definir Limites de Erro por rota. Isso permite que desenvolvedores lidem com erros em um nível mais granular. Em vez de ter um único limite de erro global para todo o aplicativo, você pode definir limites de erro específicos para rotas individuais, tornando o manejo de erros mais flexível e localizado. O manejo granular de erros no nível de rota agora é possível.
Em versões mais antigas, o manejo de erros era global ou gerenciado no nível do componente. Isso exigia que desenvolvedores lidassem com todos os possíveis erros em um único lugar ou introduzissem lógica complexa em vários componentes. Como mencionado no exemplo abaixo, o ErrorBoundary
é global porque envolve todo o Router
, significando que ele capturará erros de todas as rotas dentro do aplicativo.
Exemplo de React Router v5
function App() {
return (
<ErrorBoundary>
<Router>
<Route path="/" exact component={HomePage} />
<Route path="/about" component={AboutPage} />
</Router>
</ErrorBoundary>
);
}
React Router 7 introduces limites de erro no nível de rota, tornando possível lidar com erros para rotas específicas. Isso permite um controle mais granular sobre como os erros são gerenciados e exibidos.
Exemplo 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 />} />
Diferença
O tratamento de erros no React Router 7 é mais modular e localizado. Cada rota pode definir sua própria lógica de tratamento de erros, melhorando a experiência do usuário quando diferentes partes do aplicativo falham.
3. Melhor Manipulação de Rotas de Layout
Rotas de layout são introduzidas, permitindo uma gestão consistente de layouts em diferentes partes do aplicativo, reduzindo a duplicação de código.
No React Router v5, layouts como cabeçalhos, rodapés ou barras laterais tinham que ser manualmente duplicados em cada rota ou componente. Isso significava que os desenvolvedores frequentemente colocavam componentes de layout (por exemplo, Header
, Footer
) diretamente dentro do componente App
ou os repetiam em diferentes manipuladores de rota, como mostrado no seu exemplo.
Exemplo 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 introduces rotas de layout, onde você pode definir layouts compartilhados que envolvem rotas aninhadas, eliminando a duplicação de código e garantindo uma melhor estrutura.
Exemplo 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>
Diferença
Rotas de layout permitem uma forma limpa e reutilizável de aplicar layouts compartilhados em várias rotas, sem repetir código. Outlet
age como um espaço reservado para rotas filhas, facilitando muito a gestão de layouts.
4. Capacidades de Roteamento Aninhado Melhoradas
Existem maneiras mais eficientes de lidar com rotas aninhadas, incluindo a herança de elementos de layout e estratégias de busca de dados melhoradas.
Em versões mais antigas, era possível ter rotas aninhadas, mas a configuração era mais trabalhosa. Você tinha que lidar explicitamente com a aninhamento de rotas dentro do componente pai usando useRouteMatch()
para obter o caminho atual, e depois definir manualmente as rotas aninhadas dentro do componente pai. Esta abordagem pode rapidamente se tornar trabalhosa, especialmente para aplicações complexas com várias camadas de rotas aninhadas.
Exemplo de React Router v5
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} />
Trong React Router 7, as rotas aninhadas são agora configuradas declarativamente, diretamente dentro da configuração da rota, simplificando a estrutura de roteamento e tornando o código mais legível.
Exemplo de React Router v7
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>
Diferença
Trong React Router 7, as rotas aninhadas são mais fáceis de gerenciar porque são definidas no nível da configuração da rota usando o componente Outlet
. Esta estrutura promove uma clara separação entre layout e conteúdo.
5. Melhor Integração com Suspense
Agora, há suporte melhorado para o React 18’s Suspense
e renderização concorrente para uma experiência de carregamento mais suave.
Em versões antigas, o suspense era suportado apenas para componentes carregados de forma懒散, limitando sua utilidade para cenários de busca de dados complexos.
Exemplo de React Router v5
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
com seu Loader e Action APIs, permitindo uma busca de dados mais suave e simultânea com esforço mínimo.
Exemplo de React Router v7
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>
);
}
Diferença
React Router 7 utiliza Suspense
tanto para componentes carregados com懒惰 quanto para busca de dados, permitindo transições mais suaves e uma interface de usuário mais responsiva.
Conclusão
React Router 7 (ou a versão mais recente) melhora significativamente o roteamento em aplicações React ao introduzir várias funcionalidades poderosas. O novo Loader e Action APIs permitem a busca de dados declarativa, separando a lógica de dados dos componentes para um código mais limpo. Layout Routes simplificam a gestão de layouts compartilhados, reduzindo a redundância. Nested routes são mais eficientes e intuitivos, permitindo uma estrutura mais clara. Além disso, limites de erro por rota fornecem um manuseio de erros granular, melhorando a confiabilidade. A integração total com React Suspense
suporta um carregamento de dados mais suave e uma experiência de usuário melhor. Juntos, esses avanços simplificam o desenvolvimento de aplicações React complexas, escaláveis e de alta performance, tornando o React Router 7 uma atualização significativa em relação às versões anteriores.
Source:
https://dzone.com/articles/why-react-router-7-is-a-game-changer-for-react-devs