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ãoMais Recente)
Aqui estão algumas das melhorias significativas e funcionalidades 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 fetching e modificação de dados de maneira mais declarativa dentro das rotas.
Em versões anteriores, o fetching de dados era tipicamente tratado dentro de componentes React usando useEffect
ou métodos de ciclo de vida de componentes de classe. Isso frequentemente levava ao logic de fetching de dados ser misturado com a renderização da interface do usuário, o que podia se tornar trabalhoso.
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 últimas versões introduzem APIs Loader
, permitindo que o fetching de dados aconteça diretamente no nível da rota. Isso separa preocupações, simplifica componentes e permite uma renderização simultânea 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 os 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 antigas, o manejo de erros era global ou gerenciado no nível do componente. Isso exigia que os 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 app.
Exemplo do React Router v5
function App() {
return (
<ErrorBoundary>
<Router>
<Route path="/" exact component={HomePage} />
<Route path="/about" component={AboutPage} />
</Router>
</ErrorBoundary>
);
}
O 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 do 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 manejo de erros no React Router 7 é mais modular e localizado. Cada rota pode definir sua própria lógica de manejo de erros, melhorando a experiência do usuário quando diferentes partes do app falham.
3. Melhor Manejo de Rotas de Layout
Rotas de layout são introduzidas, permitindo uma gestão consistente de layouts em diferentes partes do app, reduzindo a duplicação de código.
No React Router v5, layouts como cabeçalhos, rodapés ou barras laterais tinham que ser duplicados manualmente em cada rota ou componente. Isso significava que desenvolvedores frequentemente posicionavam 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
As rotas de layout permitem uma forma limpa e reutilizável de aplicar layouts compartilhados em várias rotas, sem repetir o código. O Outlet
age como um espaço reservado para rotas filhas, facilitando muito o manejo 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 melhores estratégias de fetching de dados.
Em versões mais antigas, era possível ter rotas aninhadas, mas a configuração era mais trabalhosa. Você tinha que lidar explicitamente com o 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 complicada, 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} />
Em React Router 7, as rotas aninhadas agora são configuradas declarativamente, diretamente dentro da configuração de 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
No React Router 7, as rotas aninhadas são mais fáceis de gerenciar porque são definidas no nível de configuração de 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 rendering concorrente para experiências de carregamento mais suaves.
Em versões mais antigas, o suspense era suportado apenas para componentes carregados com lazy, 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 aplicativos React, introduzindo várias funcionalidades poderosas. O novo Loader e Action APIs permitem uma busca de dados declarativa, separando a lógica de dados dos componentes para código mais limpo. Layout Routes simplificam a gestão de layouts compartilhados, reduzindo a redundância. Nested routes são mais eficientes e intuitivas, 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 completa com React Suspense
suporta uma carga de dados mais suave e uma experiência de usuário melhor. Juntas, essas melhorias simplificam o desenvolvimento de aplicativos React complexos, 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