React Router: navegação em SPAs
1. Introdução ao React Router e SPAs
Single Page Applications (SPAs) são aplicações web que carregam uma única página HTML e atualizam dinamicamente o conteúdo sem recarregar a página inteira. Diferente da navegação tradicional, onde cada clique em um link faz uma requisição HTTP ao servidor e recarrega todo o documento, as SPAs manipulam o histórico do navegador via JavaScript para simular a navegação entre "páginas" virtuais.
O React Router é a biblioteca padrão para gerenciar essa navegação client-side em aplicações React. Ele sincroniza a interface com a URL do navegador, permitindo que você defina rotas, acesse parâmetros, proteja páginas e muito mais — tudo sem recarregar a página.
Para começar, instale o pacote principal:
npm install react-router-dom
A configuração básica envolve envolver sua aplicação com um roteador e definir as rotas:
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</BrowserRouter>
);
}
2. Componentes Fundamentais do React Router
BrowserRouter vs HashRouter
BrowserRouter: Usa a API de histórico do HTML5 para manter a UI sincronizada com a URL. As URLs são limpas (ex:/about). Requer configuração no servidor para redirecionar todas as requisições para oindex.html.HashRouter: Usa o hash da URL (ex:/#/about). Funciona sem configuração de servidor, pois o hash nunca é enviado ao servidor. Útil para protótipos ou quando você não controla o servidor.
Routes e Route
O componente Routes agrupa todas as rotas. Cada Route define um caminho (path) e o componente a ser renderizado (element):
<Routes>
<Route path="/" element={<Home />} />
<Route path="/products" element={<Products />} />
<Route path="/contact" element={<Contact />} />
</Routes>
Link e NavLink
Link substitui a tag <a> tradicional, prevenindo o recarregamento da página:
<Link to="/about">Sobre</Link>
NavLink é uma versão especial que adiciona automaticamente uma classe CSS quando a rota está ativa:
<NavLink to="/about" className={({ isActive }) => isActive ? 'active' : ''}>
Sobre
</NavLink>
3. Navegação Programática e Parâmetros de Rota
useNavigate
Para redirecionar via JavaScript (após login, envio de formulário, etc.), use o hook useNavigate:
import { useNavigate } from 'react-router-dom';
function LoginForm() {
const navigate = useNavigate();
const handleSubmit = async (e) => {
e.preventDefault();
// lógica de autenticação
await loginUser(data);
navigate('/dashboard');
};
return <form onSubmit={handleSubmit}>...</form>;
}
Parâmetros Dinâmicos com useParams
Defina parâmetros na rota usando : e acesse-os com useParams:
// Configuração da rota
<Route path="/user/:id" element={<UserProfile />} />
// Componente UserProfile
import { useParams } from 'react-router-dom';
function UserProfile() {
const { id } = useParams();
return <h1>Perfil do usuário {id}</h1>;
}
Parâmetros de Consulta com useSearchParams
Para ler e modificar query strings, use useSearchParams:
import { useSearchParams } from 'react-router-dom';
function ProductList() {
const [searchParams, setSearchParams] = useSearchParams();
const category = searchParams.get('category') || 'all';
const filterByCategory = (cat) => {
setSearchParams({ category: cat });
};
return (
<div>
<button onClick={() => filterByCategory('electronics')}>
Eletrônicos
</button>
<p>Exibindo produtos da categoria: {category}</p>
</div>
);
}
4. Rotas Aninhadas e Layouts Compartilhados
O React Router permite criar estruturas de rotas hierárquicas usando o componente Outlet. Isso é ideal para layouts compartilhados (header, footer, sidebar).
// App.js
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Layout from './Layout';
import Home from './Home';
import Products from './Products';
import ProductDetail from './ProductDetail';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="products" element={<Products />} />
<Route path="products/:id" element={<ProductDetail />} />
</Route>
</Routes>
</BrowserRouter>
);
}
// Layout.js
import { Outlet, Link } from 'react-router-dom';
function Layout() {
return (
<div>
<header>
<nav>
<Link to="/">Home</Link>
<Link to="/products">Produtos</Link>
</nav>
</header>
<main>
<Outlet /> {/* Aqui o conteúdo da rota filha será renderizado */}
</main>
<footer>© 2025 Minha Loja</footer>
</div>
);
}
Rotas relativas em componentes aninhados usam caminhos sem barra inicial ("products" em vez de "/products"). Para caminhos absolutos, use a barra ("/products").
5. Proteção de Rotas e Autenticação
Para criar rotas privadas, implemente um componente ProtectedRoute que verifica o estado de autenticação:
import { Navigate, Outlet } from 'react-router-dom';
function ProtectedRoute({ isAuthenticated, redirectPath = '/login' }) {
if (!isAuthenticated) {
return <Navigate to={redirectPath} replace />;
}
return <Outlet />;
}
Uso no roteador:
<Routes>
<Route path="/login" element={<Login />} />
<Route element={<ProtectedRoute isAuthenticated={user !== null} />}>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/settings" element={<Settings />} />
</Route>
</Routes>
Para persistência de sessão, armazene tokens no localStorage ou sessionStorage e verifique ao carregar a aplicação:
function App() {
const [user, setUser] = useState(() => {
const saved = localStorage.getItem('user');
return saved ? JSON.parse(saved) : null;
});
return (
<BrowserRouter>
<Routes>
<Route path="/login" element={<Login setUser={setUser} />} />
<Route element={<ProtectedRoute isAuthenticated={!!user} />}>
<Route path="/dashboard" element={<Dashboard />} />
</Route>
</Routes>
</BrowserRouter>
);
}
6. Tratamento de Erros e Rotas Coringa
Rota 404
Use path="*" para capturar qualquer URL não definida:
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="*" element={<NotFound />} />
</Routes>
Componente Navigate para Redirecionamentos Condicionais
Além do useNavigate, você pode usar o componente Navigate para redirecionamentos declarativos:
import { Navigate } from 'react-router-dom';
function OldPage() {
return <Navigate to="/new-page" replace />;
}
Tratamento de Erros de Navegação
Crie um fallback para erros inesperados usando Error Boundaries combinados com o React Router:
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
render() {
if (this.state.hasError) {
return <h1>Algo deu errado. <Link to="/">Voltar ao início</Link></h1>;
}
return this.props.children;
}
}
7. Otimização com Lazy Loading e Code Splitting
Para melhorar a performance em SPAs, carregue componentes de rota sob demanda usando React.lazy e Suspense:
import { lazy, Suspense } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));
const Products = lazy(() => import('./pages/Products'));
function App() {
return (
<BrowserRouter>
<Suspense fallback={<div>Carregando...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/products" element={<Products />} />
</Routes>
</Suspense>
</BrowserRouter>
);
}
Isso reduz o bundle inicial, pois cada página só é carregada quando o usuário a acessa. Combine com ferramentas como Webpack ou Vite para divisão automática de código.
Boas práticas adicionais:
- Use React.lazy apenas para componentes de página, não para componentes pequenos.
- Forneça um fallback visualmente agradável no Suspense.
- Considere pré-carregar rotas prováveis com React.lazy + preload para melhorar a experiência do usuário.
Referências
- Documentação oficial do React Router v6 — Guia completo com todos os hooks, componentes e exemplos práticos.
- React Router: Navegação Programática — Referência detalhada do hook
useNavigatee suas variações. - Code Splitting com React.lazy — Documentação oficial do React sobre lazy loading e Suspense.
- Autenticação em SPAs com React Router — Tutorial prático de como implementar rotas protegidas e fluxo de login/logout.
- React Router v6: Guia Completo — Artigo técnico abordando desde conceitos básicos até padrões avançados como rotas aninhadas e lazy loading.
- React Router: Tratamento de Erros e Rotas 404 — Tutorial sobre como criar páginas de erro personalizadas e lidar com redirecionamentos.