Introdução ao React Router
React Router é a biblioteca padrão para navegação em aplicações React modernas. Ela permite criar uma experiência de usuário fluida sem recarregar a página, mantendo o histórico do navegador e sincronizando a URL com o estado da aplicação. Dominar Router é essencial para construir SPAs (Single Page Applications) profissionais e escaláveis.
Neste artigo, vamos cobrir desde configuração básica até proteção de rotas avançada. Você aprenderá a criar navegações eficientes, trabalhar com parâmetros dinâmicos e implementar autenticação em rotas privadas. Assumo que você já conhece React hooks e componentes funcionais.
Configuração Básica e Rotas Estáticas
Setup Inicial
Comece instalando React Router v6 (versão atual estável):
npm install react-router-dom
A configuração envolve envolver sua aplicação com BrowserRouter e definir rotas usando Routes e Route:
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Contact from './pages/Contact';
export default function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</Router>
);
}
Cada rota mapeia um caminho (path) a um componente (element). Quando o usuário navega para uma URL, React Router renderiza o componente correspondente sem recarregar a página. A ordem das rotas importa: React Router usa a primeira que encontra correspondência.
Navegação com Link e useNavigate
Para navegar sem recarregar, use o componente Link ou o hook useNavigate. Link é ideal para navegação declarativa em componentes, enquanto useNavigate oferece controle programático:
import { Link, useNavigate } from 'react-router-dom';
export default function Navbar() {
const navigate = useNavigate();
const handleLogout = () => {
sessionStorage.removeItem('token');
navigate('/login');
};
return (
<nav>
<Link to="/">Home</Link>
<Link to="/about">Sobre</Link>
<button onClick={handleLogout}>Logout</button>
</nav>
);
}
Rotas Dinâmicas e Parâmetros
Parâmetros de URL
Rotas dinâmicas capturam partes variáveis da URL usando dois-pontos (:paramName). Acesse-os com o hook useParams:
// Em App.jsx
<Route path="/product/:id" element={<ProductDetail />} />
// Em ProductDetail.jsx
import { useParams } from 'react-router-dom';
export default function ProductDetail() {
const { id } = useParams();
const [product, setProduct] = React.useState(null);
React.useEffect(() => {
fetch(`/api/products/${id}`)
.then(res => res.json())
.then(data => setProduct(data));
}, [id]);
if (!product) return <div>Carregando...</div>;
return (
<div>
<h1>{product.name}</h1>
<p>Preço: R$ {product.price}</p>
</div>
);
}
Query Strings
Para parâmetros opcionais na query string (ex: /products?sort=price&filter=active), use useSearchParams:
import { useSearchParams } from 'react-router-dom';
export default function Products() {
const [searchParams, setSearchParams] = useSearchParams();
const sort = searchParams.get('sort') || 'name';
const filter = searchParams.get('filter') || 'all';
const handleFilterChange = (newSort) => {
setSearchParams({ sort: newSort, filter });
};
return (
<div>
<button onClick={() => handleFilterChange('price')}>
Ordenar por Preço
</button>
<p>Ordenação atual: {sort}</p>
</div>
);
}
Proteção de Rotas e Autenticação
PrivateRoute com Contexto
Rotas protegidas garantem que apenas usuários autenticados acessem certas páginas. Implemente um contexto de autenticação e um componente wrapper:
// AuthContext.jsx
import React, { createContext, useState, useEffect } from 'react';
export const AuthContext = createContext();
export function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const token = localStorage.getItem('token');
if (token) {
// Validar token com backend
fetch('/api/auth/validate', {
headers: { Authorization: `Bearer ${token}` }
})
.then(res => res.json())
.then(data => setUser(data))
.catch(() => setUser(null))
.finally(() => setLoading(false));
} else {
setLoading(false);
}
}, []);
return (
<AuthContext.Provider value={{ user, setUser, loading }}>
{children}
</AuthContext.Provider>
);
}
// PrivateRoute.jsx
import { Navigate } from 'react-router-dom';
import { useContext } from 'react';
import { AuthContext } from './AuthContext';
export function PrivateRoute({ children }) {
const { user, loading } = useContext(AuthContext);
if (loading) return <div>Carregando...</div>;
return user ? children : <Navigate to="/login" />;
}
// App.jsx
<AuthProvider>
<Router>
<Routes>
<Route path="/login" element={<Login />} />
<Route
path="/dashboard"
element={<PrivateRoute><Dashboard /></PrivateRoute>}
/>
</Routes>
</Router>
</AuthProvider>
Proteção Baseada em Roles
Para controle granular, valide permissões dentro da rota:
export function AdminRoute({ children }) {
const { user, loading } = useContext(AuthContext);
if (loading) return <div>Carregando...</div>;
if (!user) return <Navigate to="/login" />;
if (user.role !== 'admin') return <Navigate to="/unauthorized" />;
return children;
}
// Uso
<Route
path="/admin"
element={<AdminRoute><AdminPanel /></AdminRoute>}
/>
Recursos Avançados
Layouts Aninhados
Use layouts compartilhados para múltiplas rotas com Outlet:
import { Outlet } from 'react-router-dom';
export function Layout() {
return (
<div>
<Navbar />
<Outlet /> {/* Renderiza a rota filha aqui */}
<Footer />
</div>
);
}
// Em App.jsx
<Route element={<Layout />}>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Route>
Tratamento de Rotas Não Encontradas
Adicione um catch-all no final para páginas 404:
<Route path="*" element={<NotFound />} />
Conclusão
React Router v6 simplifica navegação em SPAs através de três pilares: rotas estáticas e dinâmicas para mapear URLs a componentes, parâmetros e query strings para compartilhar dados entre telas, e proteção via contexto e componentes wrapper para segurança. Pratique combinando esses conceitos em um projeto real — um e-commerce ou dashboard de admin são ótimos casos de uso.
A chave para dominar Router é entender que ela sincroniza três elementos: URL, histórico do navegador e estado da aplicação. Domine isso e você construirá navegações robustas e profissionais.