React Router DOM: como funciona o roteamento em aplicações React

Rocketseat

Rocketseat

11 min de leitura
react
Imagine que você está construindo uma cidade digital. Cada prédio, praça ou loja é um componente React. Como os habitantes (usuários) se movem de um lugar para outro? Eles precisam de ruas e endereços. Em uma aplicação web, essas ruas são as URLs, e o sistema que gerencia essas rotas é o React Router DOM.
Se você está começando em React e a ideia de roteamento React parece um mapa complexo, pode relaxar. Estamos aqui para te guiar, passo a passo. Acredite, é totalmente possível começar e dominar a navegação SPA em suas aplicações. Este material foi feito para quem já deu os primeiros passos com componentes e estado, e agora quer construir aplicações mais completas e dinâmicas.

O que é o React Router DOM e por que usar?

O React Router DOM é a biblioteca padrão da comunidade para lidar com roteamento em aplicações React. De forma simples, ela permite que sua aplicação tenha múltiplas "páginas" ou "telas", mesmo sendo tecnicamente uma única página. É a ferramenta que sincroniza a interface da sua aplicação com a URL no navegador, permitindo uma navegação fluida sem a necessidade de recarregar a página inteira a cada clique.
Pense em como você navega no Instagram ou no Facebook. Ao clicar em um perfil ou em uma foto, o conteúdo da página muda instantaneamente, a URL é atualizada, mas o navegador não faz aquele "piscar" de recarregamento total. Isso é o roteamento do lado do cliente (client-side routing) em ação, uma das principais características de uma Single-Page Application (SPA).

Aplicações de página única vs. aplicações com múltiplas rotas

Para entender o valor do React Router, é importante diferenciar dois modelos de arquitetura web. Uma aplicação tradicional, conhecida como Multi-Page Application (MPA), funciona como a web funcionava em seus primórdios. Cada vez que você clica em um link, o navegador envia uma requisição ao servidor, que por sua vez devolve um arquivo HTML completamente novo. Esse processo causa um recarregamento total da página.
Já uma Single-Page Application (SPA), o modelo que o React popularizou, carrega um único arquivo HTML inicial. A partir daí, toda a navegação e alteração de conteúdo são gerenciadas por JavaScript diretamente no navegador do usuário. O React Router é a biblioteca que possibilita que uma SPA simule múltiplas páginas, alterando o que é exibido na tela com base na URL, mas sem novos recarregos.
A escolha entre esses dois modelos arquitetônicos impacta diretamente a estratégia do produto. Uma SPA, com sua experiência de usuário fluida e rápida, é ideal para aplicações onde a retenção e o engajamento são cruciais, como dashboards, ferramentas SaaS e redes sociais. Por outro lado, o modelo MPA, por ter cada página como um documento separado, tende a ser mais facilmente indexado por buscadores, sendo uma escolha forte para negócios que dependem de tráfego orgânico para aquisição de clientes, como blogs e grandes sites de e-commerce. Portanto, ao aprender a construir SPAs com roteamento, a pessoa desenvolvedora está adquirindo uma habilidade que influencia diretamente o posicionamento de um produto no mercado.
A tabela a seguir resume as principais diferenças:
Característica
SPA
MPA
Experiência do usuário
Fluida e rápida, sem recarregamentos a cada clique.
Interrupções visíveis a cada navegação com recarregamento da página.
Performance
Carga inicial pode ser maior, mas a navegação entre páginas é quase instantânea.
Carga inicial de cada página é independente e geralmente mais rápida, mas a navegação é mais lenta.
SEO
Requer técnicas específicas para garantir a indexação correta do conteúdo.
Amigável por padrão, pois cada página é um HTML distinto e facilmente rastreável.
Complexidade de desenvolvimento
Geralmente promove um desacoplamento claro entre front-end e back-end.
A lógica de front-end e back-end pode ser mais interligada.
Casos de uso ideais
Dashboards, redes sociais, aplicações SaaS, onde a experiência interativa é prioridade.
Blogs, sites de notícias, e-commerce com vasto catálogo de produtos.

Vantagens do roteamento client-side

Adotar o roteamento client-side com o React Router DOM traz benefícios concretos para suas aplicações single-page:
  • Performance e UX fluida: como não há recarregamento completo da página, as transições entre diferentes seções da aplicação são muito mais rápidas e suaves, proporcionando uma experiência de usuário similar à de um aplicativo nativo de desktop ou mobile.
  • URLs compartilháveis: cada visualização da sua aplicação pode ter uma URL única. Isso significa que a pessoa usuária pode favoritar uma página específica ou compartilhar um link direto para um conteúdo, algo que seria complexo em uma SPA sem um sistema de roteamento.
  • Navegação consistente: ele se integra perfeitamente com os botões de "voltar" e "avançar" do navegador, mantendo o comportamento esperado pelo usuário e melhorando a usabilidade.
  • A URL como fonte de estado: a URL se torna uma parte confiável do estado da sua aplicação. Você pode usar a informação contida nela para decidir o que renderizar, qual dado buscar e como a interface deve se comportar.
É válido notar que essa performance aprimorada na navegação vem com uma contrapartida. A carga inicial de uma SPA pode ser um pouco mais demorada, pois o navegador precisa baixar não apenas o código da página inicial, mas também o JavaScript necessário para gerenciar todas as outras rotas possíveis. Para contornar isso em aplicações maiores, profissionais de tecnologia utilizam técnicas como code-splitting (divisão de código), que permite carregar o código de cada rota apenas quando ele é necessário.

Primeiros passos com React Router DOM

Vamos colocar a mão na massa. Esta seção é um guia prático para você instalar e configurar o roteamento em um novo projeto React.

Instalação e configuração inicial

Para começar a usar o React Router DOM, o primeiro passo é instalá-lo em seu projeto. Abra o terminal na pasta raiz do seu projeto React e execute o seguinte comando:
npm install react-router-dom
Este comando adiciona o react-router-dom como uma dependência no seu arquivo package.json.
Após a instalação, você verá uma entrada similar a esta na seção de dependências do seu arquivo:
"dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.23.1", // exemplo de versão ... ... ... },
Com a biblioteca instalada, já podemos começar a configurar nossa estrutura.

Estrutura básica de um projeto com roteamento

Manter um projeto organizado é um passo importante para a manutenibilidade. Uma convenção comum em projetos React é separar os componentes que representam páginas inteiras dos componentes de UI reutilizáveis.
Para iniciantes, sugerimos a seguinte estrutura de pastas:
/src |-- /components // Componentes de UI reutilizáveis (Button, Input, Card, etc.) |-- /pages // Componentes que representam uma página (Home, Sobre, Contato) |-- App.js // Onde a configuração das rotas vai morar |-- index.js // Ponto de entrada da aplicação
O próximo passo é "habilitar" o roteamento em toda a aplicação. Isso é feito envolvendo nosso componente principal, o App, com um componente do React Router chamado BrowserRouter. Essa estrutura é um exemplo prático de um padrão de projeto muito poderoso em React, o Provider Pattern.
Ao envolver a aplicação com <BrowserRouter>, você está criando um "contexto de roteamento". Esse contexto disponibiliza todas as funcionalidades de navegação para qualquer componente dentro da árvore, sem a necessidade de passar props manualmente. É por isso que hooks como useNavigate e useParams, que veremos mais adiante, funcionam de forma tão integrada em qualquer parte do seu app.

Componentes principais do React Router DOM

O React Router DOM opera com base em alguns componentes principais. Entender o papel de cada um é o que vai te dar a confiança para construir qualquer fluxo de navegação.

BrowserRouter como provedor de contexto

O BrowserRouter é o componente que ativa o roteamento na sua aplicação. Ele deve envolver o componente raiz do seu app, geralmente no arquivo src/index.js ou src/main.jsx. Ele utiliza a API de Histórico nativa do navegador para manter a sua interface sincronizada com a URL, sendo o verdadeiro "cérebro" da operação.
Veja como fica a configuração no ponto de entrada da aplicação:
import React from 'react'; import ReactDOM from 'react-dom/client'; import { BrowserRouter } from 'react-router-dom'; import App from './App'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <BrowserRouter> <App /> </BrowserRouter> </React.StrictMode> );
Embora o BrowserRouter seja o mais comum para aplicações web, existem outros tipos de roteadores para cenários específicos, como o MemoryRouter para ambientes que não possuem uma barra de endereço, como em testes ou em aplicações React Native.

Routes e Route, definindo as rotas

Uma vez que o BrowserRouter está configurado, você precisa definir quais "páginas" sua aplicação terá. Isso é feito com os componentes Routes e Route.
  • <Routes>: sua função é analisar todas as suas rotas filhas (<Route>) e renderizar aquela que melhor corresponde à URL atual do navegador.
  • <Route>: cada componente <Route> é uma declaração de mapeamento. Ele conecta um path (o caminho na URL, como /sobre) a um element (o componente React que deve ser exibido nesse caminho).
Aqui está um exemplo prático de como definir algumas rotas dentro do seu componente App:
import { Routes, Route } from 'react-router-dom'; import Home from './pages/Home'; import Profile from './pages/Profile'; import Settings from './pages/Settings'; // Criando componentes const Mayk = () => <div>Página inicial do Mayk</div>; const Diego = () => <div>Página de perfil do Diego</div>; const Rodrigo = () => <div>Página de configurações do Rodrigo</div>; function App() { return ( <div> <Routes> <Route path="/" element={<Mayk />} /> <Route path="/diego" element={<Diego />} /> <Route path="/rodrigo" element={<Rodrigo />} /> </Routes> </div> ); }

Navegação entre páginas com Link e NavLink

Com as rotas definidas, como o usuário navega entre elas? Se você usar a tag <a> do HTML tradicional, você quebrará a experiência de uma SPA. Uma tag <a> com href sempre acionará um recarregamento completo da página, perdendo todo o estado da sua aplicação React e causando um "piscar" na tela.
A solução do React Router é o componente <Link>. Ele renderiza uma tag <a> no HTML final, mas intercepta o evento de clique. Em vez de deixar o navegador fazer o recarregamento, o <Link> atualiza a URL programaticamente e informa ao React Router para renderizar o novo componente correspondente. Essa troca de responsabilidade é o que define o "contrato" de uma SPA: a aplicação, e não o navegador, assume o controle da navegação.
  • <Link>: para criar links de navegação básicos.
  • <NavLink>: variação especial do <Link> que "sabe" quando a rota para a qual ele aponta está ativa. Isso é extremamente útil para estilizar o link da página atual em um menu de navegação, por exemplo, destacando-o.
Veja a diferença na prática:
import { Link, NavLink } from 'react-router-dom'; function Navigation() { return ( <nav> {/* Link simples para a página inicial */} <Link to="/">Home</Link> {/* NavLink para a página "Sobre", com estilo condicional */} <NavLink to="/sobre" style={({ isActive }) => { return { fontWeight: isActive ? 'bold' : 'normal', color: isActive? "#8257E5" : "black", }; }} > Sobre </NavLink> </nav> ); }

Configurando o projeto do zero

Crie um novo projeto React com o Vite (a ferramenta recomendada atualmente) ou Create React App:
npm create vite@latest meu-app-roteado -- --template react cd meu-app-roteado
Instale o React Router DOM:
npm install react-router-dom
Crie a estrutura de pastas que sugerimos anteriormente, com uma pasta pages dentro de src.

Implementando páginas básicas

Dentro de src/pages, crie três arquivos: Home.jsx, Sobre.jsx e Contato.jsx.
src/pages/Home.jsx:
const Home = () => { return <h1>Página Inicial</h1>; }; export default Home;
src/pages/Sobre.jsx:
const Sobre = () => { // Usando nomes fictícios da comunidade Rocketseat, como pedido no plano const equipe = [ { id: 1, nome: "Laís" }, { id: 2, nome: "Isabela" }, { id: 3, nome: "Fernanda" }, ]; return ( <div> <h1>Sobre Nós</h1> <p>Nossa equipe é formada por: {equipe.map(m => m.nome).join(', ')}.</p> </div> ); }; export default Sobre;
src/pages/Contato.jsx:
const Contato = () => { return <h1>Página de Contato</h1>; }; export default Contato;
Agora, vamos configurar o arquivo principal src/App.jsx para usar essas páginas e criar a navegação.
src/App.jsx:
import { Routes, Route, Link } from 'react-router-dom'; import Home from './pages/Home'; import Sobre from './pages/Sobre'; import Contato from './pages/Contato'; import './App.css'; // Estilização básica function App() { return ( <div className="App"> <header> <nav> <Link to="/">Home</Link> <Link to="/sobre">Sobre</Link> <Link to="/contato">Contato</Link> </nav> </header> <main> <Routes> <Route path="/" element={<Home />} /> <Route path="/sobre" element={<Sobre />} /> <Route path="/contato" element={<Contato />} /> </Routes> </main> </div> ); } export default App;
Não se esqueça de envolver o <App /> com <BrowserRouter> no seu arquivo src/main.jsx.
src/main.jsx:
import React from 'react'; import ReactDOM from 'react-dom/client'; import { BrowserRouter } from 'react-router-dom'; import App from './App'; import './index.css'; ReactDOM.createRoot(document.getElementById('root')).render( <React.StrictMode> <BrowserRouter> <App /> </BrowserRouter> </React.StrictMode> );

Testando a navegação

Execute sua aplicação com npm run dev (para Vite) ou npm start (para Create React App). Você verá sua aplicação com os três links de navegação. Clique neles e observe:
  • A URL na barra de endereços do navegador muda.
  • O conteúdo da página (o <h1>) muda para corresponder à página clicada.
  • A página inteira não recarrega.
Parabéns, você acabou de criar sua primeira aplicação React com roteamento!

Conceitos para expandir conhecimento

Com a base sólida, podemos explorar alguns padrões mais avançados que são comuns em aplicações do mundo real.

Parâmetros de rota e dados dinâmicos

Muitas vezes, você precisará de rotas que não são fixas, mas dinâmicas. Por exemplo, a página de perfil de um usuário (/perfil/diego), a página de um produto (/produtos/cadeira-gamer) ou de um post de blog (/blog/guia-de-react). Seria inviável criar uma rota para cada usuário ou produto.
É aqui que entram os parâmetros de rota. Você pode definir um "segmento dinâmico" na sua rota usando dois pontos (:). Para acessar o valor desse parâmetro dentro do seu componente, você usa o hook useParams.
Este conceito marca um salto importante na sua jornada: a URL deixa de ser apenas um endereço e se torna parte do estado da sua aplicação. O parâmetro extraído da URL, como um ID, é frequentemente usado para buscar dados específicos de uma API. Assim, a URL passa a ditar diretamente o conteúdo exibido, permitindo que um único componente sirva para criar um número infinito de páginas únicas.
Exemplo:
Defina a rota dinâmica em App.jsx:
<Route path="/perfil/:userId" element={<UserProfile />} />
Crie o componente UserProfile.jsx e use o hook useParams:
// src/pages/UserProfile.jsx import { useParams } from 'react-router-dom'; function UserProfile() { // O hook useParams retorna um objeto com os parâmetros da URL. // A chave do objeto é o nome que demos ao parâmetro na rota (:userId). let { userId } = useParams(); return ( <div> <h2>Perfil do usuário:</h2> <p>Exibindo informações: <strong>{userId}</strong>.</p> </div> ); } export default UserProfile;
Agora, se você navegar para /perfil/mayk, o componente renderizará "Exibindo informações para o usuário: mayk". Se for para /perfil/rodrigo, o nome mudará de acordo.

Rotas aninhadas e layouts

Aplicações complexas frequentemente possuem layouts compartilhados. Imagine um painel de controle (dashboard) com uma barra lateral e um cabeçalho que permanecem os mesmos enquanto o conteúdo principal muda. As rotas aninhadas são a solução perfeita para isso.
O padrão consiste em criar uma rota "pai" que renderiza o layout compartilhado. Dentro desse componente de layout, você usa o componente <Outlet />. Ele funciona como um marcador de posição, indicando onde os componentes das rotas "filhas" devem ser renderizados.
Essa abordagem é uma aplicação poderosa do princípio de composição e da filosofia "Don't Repeat Yourself" (DRY) na arquitetura de UI. O layout compartilhado é definido uma única vez, e o <Outlet /> desacopla essa estrutura do conteúdo dinâmico. Para alterar o cabeçalho de todas as páginas do dashboard, você edita apenas um arquivo, tornando a aplicação muito mais fácil de manter e escalar.
Exemplo:
Crie um componente de layout:
// src/layouts/DashboardLayout.jsx import { Outlet, Link } from 'react-router-dom'; const DashboardLayout = () => ( <div> <header> <h1>Meu Dashboard</h1> </header> <aside> <nav> <Link to="/dashboard">Início</Link> | <Link to="/dashboard/stats">Estatísticas</Link> </nav> </aside> <main> {/* O conteúdo das rotas aninhadas será renderizado aqui */} <Outlet /> </main> </div> ); export default DashboardLayout;
Configure as rotas aninhadas em App.jsx:
import DashboardLayout from './layouts/DashboardLayout'; import DashboardHome from './pages/DashboardHome'; import DashboardStats from './pages/DashboardStats'; <Routes> {/*... outras rotas... */} <Route path="/dashboard" element={<DashboardLayout />}> <Route index element={<DashboardHome />} /> {/* Rota padrão para /dashboard */} <Route path="stats" element={<DashboardStats />} /> {/* Rota para /dashboard/stats */} </Route> </Routes>

Tratamento de rotas não encontradas (404)

O que acontece quando um usuário tenta acessar uma URL que não existe na sua aplicação? Por padrão, ele verá uma página em branco. Uma boa experiência de usuário exige uma página de "Não Encontrado" (404).
No React Router, você pode criar uma rota “pega-tudo” usando um asterisco (*) como path. Essa rota será renderizada apenas se nenhuma outra rota mais específica for encontrada.
Exemplo:
import NotFoundPage from './pages/NotFoundPage'; <Routes> <Route path="/" element={<Home />} /> <Route path="/sobre" element={<Sobre />} /> <Route path="*" element={<NotFoundPage />} /> // <---- </Routes>
Uma estratégia de 404 robusta precisa considerar dois cenários. A rota path="*" resolve perfeitamente os erros de navegação dentro da aplicação já carregada. Mas há uma armadilha comum para iniciantes: o erro 404 que acontece no servidor quando o usuário atualiza a página em uma rota aninhada (ex: F5 em /dashboard/stats) ou a acessa diretamente. Nesse caso, o navegador pede ao servidor o arquivo /dashboard/stats, que não existe, resultando em um 404 do servidor antes mesmo do React carregar. A solução completa envolve uma configuração no servidor de hospedagem (uma regra de reescrita) para que qualquer requisição de rota seja direcionada para o index.html principal, permitindo que o React Router assuma o controle.

Novidades do React Router v7 que você deve conhecer

A versão 7 representa um grande passo, transformando a biblioteca em algo muito mais poderoso. Fique tranquilo, a atualização da v6 para a v7 é projetada para ser não-quebrável (com as future flags necessárias), o que significa que tudo o que você aprendeu até aqui continua válido.

Introdução aos loaders e actions

Esta é talvez a mudança mais significativa. Tradicionalmente, a busca de dados em React acontece dentro de um componente, geralmente com o hook useEffect, o que pode levar a exibições de "loading...". O React Router v7 introduz um novo padrão:
  • loaders: funções que você exporta de um módulo de rota para buscar dados antes que o componente seja renderizado. A página só é exibida quando os dados já estão disponíveis, eliminando a necessidade de gerenciar estados de carregamento no componente.
  • actions: funções que lidam com mutações de dados, como o envio de um formulário. Elas são acionadas por submissões de formulários e executam a lógica de criar, atualizar ou deletar dados.
O mais interessante é a integração entre eles: quando uma action é concluída com sucesso, o React Router automaticamente executa novamente o loader daquela página para buscar os dados atualizados, mantendo a UI sempre sincronizada com o back-end.
Essa mudança de paradigma transforma o React Router de uma simples biblioteca de renderização para um framework de fluxo de dados, aproximando-o de soluções full-stack como Next.js e Remix.
Video preview

Melhorias na tipagem e segurança

Com a introdução de loaders e actions, garantir que os dados que fluem pela aplicação tenham o formato correto se torna crucial. A v7 traz um suporte muito aprimorado para TypeScript, oferecendo tipagem automática para os dados retornados pelos loaders, para os actions e até para os parâmetros de rota do useParams. Isso ajuda a pessoa desenvolvedora a pegar erros durante o desenvolvimento, e não em produção.

Framework mode e suas possibilidades

O React Router v7 agora pode ser utilizado como um framework completo. Esse "Framework Mode" é, na essência, a integração do poderoso framework Remix dentro do React Router. Ele oferece uma solução completa com servidor de desenvolvimento integrado (baseado no Vite), renderização no lado do servidor (SSR), otimizações de build e muito mais, tudo pronto para usar.

Sua jornada com React Router

A jornada que você fez neste artigo, do básico do <Link> até os conceitos avançados de loaders e actions da v7, é um reflexo da evolução da pessoa desenvolvedora frontend. Não se trata mais apenas de renderizar componentes, mas de orquestrar arquiteturas de dados complexas e construir experiências de usuário ricas e performáticas.
Na Rocketseat, estamos sempre conectados com essa evolução do mercado. É por isso que, além das nossas trilhas consolidadas, estamos expandindo nossos conteúdos para cobrir as ferramentas mais modernas. Se você sentiu a empolgação de construir aplicações mais robustas e quer transformar esse conhecimento em uma base sólida para sua carreira, sua próxima parada é a nossa Formação em React. Lá, você encontrará um caminho estruturado para se aprofundar não só em roteamento, mas em todo o ecossistema React que o mercado de trabalho procura.
Video preview
Artigos_

Explore conteúdos relacionados

Descubra mais artigos que complementam seu aprendizado e expandem seu conhecimento.