JavaScript

O que Todo Dev Deve Saber sobre React Router: Navegação, Rotas Dinâmicas e Proteção de Rotas

9 min de leitura

O que Todo Dev Deve Saber sobre React Router: Navegação, Rotas Dinâmicas e Proteção de Rotas

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): A configuração envolve envolver sua aplicação com e definir rotas usando e : Cada rota mapeia um caminho ( ) a um componente ( ). 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

<h2>Introdução ao React Router</h2>

<p>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.</p>

<p>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.</p>

<h2>Configuração Básica e Rotas Estáticas</h2>

<h3>Setup Inicial</h3>

<p>Comece instalando React Router v6 (versão atual estável):</p>

<pre><code class="language-bash">npm install react-router-dom</code></pre>

<p>A configuração envolve envolver sua aplicação com <code>BrowserRouter</code> e definir rotas usando <code>Routes</code> e <code>Route</code>:</p>

<pre><code class="language-jsx">import React from &#039;react&#039;;

import { BrowserRouter as Router, Routes, Route } from &#039;react-router-dom&#039;;

import Home from &#039;./pages/Home&#039;;

import About from &#039;./pages/About&#039;;

import Contact from &#039;./pages/Contact&#039;;

export default function App() {

return (

&lt;Router&gt;

&lt;Routes&gt;

&lt;Route path=&quot;/&quot; element={&lt;Home /&gt;} /&gt;

&lt;Route path=&quot;/about&quot; element={&lt;About /&gt;} /&gt;

&lt;Route path=&quot;/contact&quot; element={&lt;Contact /&gt;} /&gt;

&lt;/Routes&gt;

&lt;/Router&gt;

);

}</code></pre>

<p>Cada rota mapeia um caminho (<code>path</code>) a um componente (<code>element</code>). 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.</p>

<h3>Navegação com Link e useNavigate</h3>

<p>Para navegar sem recarregar, use o componente <code>Link</code> ou o hook <code>useNavigate</code>. <code>Link</code> é ideal para navegação declarativa em componentes, enquanto <code>useNavigate</code> oferece controle programático:</p>

<pre><code class="language-jsx">import { Link, useNavigate } from &#039;react-router-dom&#039;;

export default function Navbar() {

const navigate = useNavigate();

const handleLogout = () =&gt; {

sessionStorage.removeItem(&#039;token&#039;);

navigate(&#039;/login&#039;);

};

return (

&lt;nav&gt;

&lt;Link to=&quot;/&quot;&gt;Home&lt;/Link&gt;

&lt;Link to=&quot;/about&quot;&gt;Sobre&lt;/Link&gt;

&lt;button onClick={handleLogout}&gt;Logout&lt;/button&gt;

&lt;/nav&gt;

);

}</code></pre>

<h2>Rotas Dinâmicas e Parâmetros</h2>

<h3>Parâmetros de URL</h3>

<p>Rotas dinâmicas capturam partes variáveis da URL usando dois-pontos (<code>:paramName</code>). Acesse-os com o hook <code>useParams</code>:</p>

<pre><code class="language-jsx">// Em App.jsx

&lt;Route path=&quot;/product/:id&quot; element={&lt;ProductDetail /&gt;} /&gt;

// Em ProductDetail.jsx

import { useParams } from &#039;react-router-dom&#039;;

export default function ProductDetail() {

const { id } = useParams();

const [product, setProduct] = React.useState(null);

React.useEffect(() =&gt; {

fetch(/api/products/${id})

.then(res =&gt; res.json())

.then(data =&gt; setProduct(data));

}, [id]);

if (!product) return &lt;div&gt;Carregando...&lt;/div&gt;;

return (

&lt;div&gt;

&lt;h1&gt;{product.name}&lt;/h1&gt;

&lt;p&gt;Preço: R$ {product.price}&lt;/p&gt;

&lt;/div&gt;

);

}</code></pre>

<h3>Query Strings</h3>

<p>Para parâmetros opcionais na query string (ex: <code>/products?sort=price&amp;filter=active</code>), use <code>useSearchParams</code>:</p>

<pre><code class="language-jsx">import { useSearchParams } from &#039;react-router-dom&#039;;

export default function Products() {

const [searchParams, setSearchParams] = useSearchParams();

const sort = searchParams.get(&#039;sort&#039;) | | &#039;name&#039;; const filter = searchParams.get(&#039;filter&#039;) || &#039;all&#039;;

const handleFilterChange = (newSort) =&gt; {

setSearchParams({ sort: newSort, filter });

};

return (

&lt;div&gt;

&lt;button onClick={() =&gt; handleFilterChange(&#039;price&#039;)}&gt;

Ordenar por Preço

&lt;/button&gt;

&lt;p&gt;Ordenação atual: {sort}&lt;/p&gt;

&lt;/div&gt;

);

}</code></pre>

<h2>Proteção de Rotas e Autenticação</h2>

<h3>PrivateRoute com Contexto</h3>

<p>Rotas protegidas garantem que apenas usuários autenticados acessem certas páginas. Implemente um contexto de autenticação e um componente wrapper:</p>

<pre><code class="language-jsx">// AuthContext.jsx

import React, { createContext, useState, useEffect } from &#039;react&#039;;

export const AuthContext = createContext();

export function AuthProvider({ children }) {

const [user, setUser] = useState(null);

const [loading, setLoading] = useState(true);

useEffect(() =&gt; {

const token = localStorage.getItem(&#039;token&#039;);

if (token) {

// Validar token com backend

fetch(&#039;/api/auth/validate&#039;, {

headers: { Authorization: Bearer ${token} }

})

.then(res =&gt; res.json())

.then(data =&gt; setUser(data))

.catch(() =&gt; setUser(null))

.finally(() =&gt; setLoading(false));

} else {

setLoading(false);

}

}, []);

return (

&lt;AuthContext.Provider value={{ user, setUser, loading }}&gt;

{children}

&lt;/AuthContext.Provider&gt;

);

}

// PrivateRoute.jsx

import { Navigate } from &#039;react-router-dom&#039;;

import { useContext } from &#039;react&#039;;

import { AuthContext } from &#039;./AuthContext&#039;;

export function PrivateRoute({ children }) {

const { user, loading } = useContext(AuthContext);

if (loading) return &lt;div&gt;Carregando...&lt;/div&gt;;

return user ? children : &lt;Navigate to=&quot;/login&quot; /&gt;;

}

// App.jsx

&lt;AuthProvider&gt;

&lt;Router&gt;

&lt;Routes&gt;

&lt;Route path=&quot;/login&quot; element={&lt;Login /&gt;} /&gt;

&lt;Route

path=&quot;/dashboard&quot;

element={&lt;PrivateRoute&gt;&lt;Dashboard /&gt;&lt;/PrivateRoute&gt;}

/&gt;

&lt;/Routes&gt;

&lt;/Router&gt;

&lt;/AuthProvider&gt;</code></pre>

<h3>Proteção Baseada em Roles</h3>

<p>Para controle granular, valide permissões dentro da rota:</p>

<pre><code class="language-jsx">export function AdminRoute({ children }) {

const { user, loading } = useContext(AuthContext);

if (loading) return &lt;div&gt;Carregando...&lt;/div&gt;;

if (!user) return &lt;Navigate to=&quot;/login&quot; /&gt;;

if (user.role !== &#039;admin&#039;) return &lt;Navigate to=&quot;/unauthorized&quot; /&gt;;

return children;

}

// Uso

&lt;Route

path=&quot;/admin&quot;

element={&lt;AdminRoute&gt;&lt;AdminPanel /&gt;&lt;/AdminRoute&gt;}

/&gt;</code></pre>

<h2>Recursos Avançados</h2>

<h3>Layouts Aninhados</h3>

<p>Use layouts compartilhados para múltiplas rotas com <code>Outlet</code>:</p>

<pre><code class="language-jsx">import { Outlet } from &#039;react-router-dom&#039;;

export function Layout() {

return (

&lt;div&gt;

&lt;Navbar /&gt;

&lt;Outlet /&gt; {/ Renderiza a rota filha aqui /}

&lt;Footer /&gt;

&lt;/div&gt;

);

}

// Em App.jsx

&lt;Route element={&lt;Layout /&gt;}&gt;

&lt;Route path=&quot;/&quot; element={&lt;Home /&gt;} /&gt;

&lt;Route path=&quot;/about&quot; element={&lt;About /&gt;} /&gt;

&lt;/Route&gt;</code></pre>

<h3>Tratamento de Rotas Não Encontradas</h3>

<p>Adicione um catch-all no final para páginas 404:</p>

<pre><code class="language-jsx">&lt;Route path=&quot;*&quot; element={&lt;NotFound /&gt;} /&gt;</code></pre>

<h2>Conclusão</h2>

<p>React Router v6 simplifica navegação em SPAs através de três pilares: <strong>rotas estáticas e dinâmicas</strong> para mapear URLs a componentes, <strong>parâmetros e query strings</strong> para compartilhar dados entre telas, e <strong>proteção via contexto e componentes wrapper</strong> para segurança. Pratique combinando esses conceitos em um projeto real — um e-commerce ou dashboard de admin são ótimos casos de uso.</p>

<p>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.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://reactrouter.com/" target="_blank" rel="noopener noreferrer">React Router Documentation</a></li>

<li><a href="https://reactrouter.com/en/main/guides/upgrading-from-v5" target="_blank" rel="noopener noreferrer">React Router v6 Upgrade Guide</a></li>

<li><a href="https://developer.mozilla.org/en-US/docs/Glossary/SPA" target="_blank" rel="noopener noreferrer">MDN: Client-side Routing</a></li>

<li><a href="https://react.dev/reference/react/useContext" target="_blank" rel="noopener noreferrer">React Context API</a></li>

<li><a href="https://www.freecodecamp.org/news/react-router-v6-tutorial/" target="_blank" rel="noopener noreferrer">freeCodeCamp: React Router Tutorial</a></li>

</ul>

Comentários

Mais em JavaScript

Como Usar Iteração Avançada em JavaScript: Iterables, Generators Assíncronos em Produção
Como Usar Iteração Avançada em JavaScript: Iterables, Generators Assíncronos em Produção

Iterables e o Protocolo de Iteração Um iterable é um objeto que implementa o...

NPM e Package.json: Gerenciamento de Dependências em JavaScript na Prática
NPM e Package.json: Gerenciamento de Dependências em JavaScript na Prática

O que é NPM e por que você precisa dominar NPM (Node Package Manager) é o ger...

Testes em JavaScript: Jest, Vitest e Testing Library na Prática na Prática
Testes em JavaScript: Jest, Vitest e Testing Library na Prática na Prática

Introdução aos Frameworks de Teste em JavaScript Testes automatizados são a b...