Skip to content
This page has been auto-translated and may contain errors.View in English

Roteamento

Um app React renderiza uma árvore de componentes em um único documento HTML. Sites reais têm uma página inicial, uma página sobre, uma página de detalhes, cada uma com sua própria URL. Roteamento é como esses dois fatos se encontram: a URL decide quais componentes renderizar, e clicar no app atualiza a URL. React Router é a biblioteca que a maioria dos apps React usa para isso, e o curso dedica uma seção inteira a ela, construindo um app de aluguel de vans chamado VanLife no caminho. Este capítulo aborda as peças principais; rotas aninhadas e parâmetros de rota se constroem sobre elas.

Roteamento no lado do cliente: MPA vs SPA

Em uma aplicação multi-página tradicional (MPA), toda navegação é uma viagem de ida e volta. O navegador requisita /about ao servidor, o servidor monta uma página HTML e a devolve, e o navegador descarta a página atual para carregar a nova. Essa troca de página inteira é visível como um tremulejo característico a cada clique.

Uma aplicação de página única (SPA) carrega um documento uma única vez. O nome é um pouco enganoso: o site ainda pode ter muitas páginas na perspectiva do usuário. O que é único é o documento. Após o primeiro carregamento, o próprio app React decide o que mostrar para cada URL. Navegar para /about troca componentes dentro do app em execução, sem nenhum novo documento sendo requisitado e sem tremulejo. Se uma visualização precisa de dados frescos, o app busca JSON em background e atualiza no lugar, o padrão coberto em Buscando dados.

Roteamento no lado do cliente é o mecanismo que faz isso funcionar: uma biblioteca observa a URL, intercepta a navegação e renderiza os componentes correspondentes em vez de permitir que o navegador recarregue. Há um real prêmio em manter o documento vivo. Um carregamento de página completo apaga todo o state do React; permanecer dentro de um único documento significa que seu state sobrevive a toda navegação.

Nota sobre versão

O curso ensina React Router 6. A versão 7 mesclou React Router com Remix e consolidou os pacotes, então react-router é o caminho de importação atual. react-router-dom sobrevive na v7 como uma re-exportação e é o pacote que v6 e o curso usam, que é por que todo exemplo neste handbook importa dela; versão 8 a descartou, então uma instalação nova importa esses componentes de react-router.

React Router documenta três modos: declarativo, os componentes BrowserRouter e Route que este capítulo cobre; dados, que emparelha createBrowserRouter com loaders e actions; e framework, um plugin Vite que adiciona módulos de rota tipados, code splitting e renderização no servidor. Os nomes de componente e hook neste capítulo não mudam entre essas versões.

BrowserRouter, Routes e Route

Três componentes definem uma configuração básica: BrowserRouter envolve o app e habilita o roteamento, Routes contém suas definições de rota, e cada Route mapeia um caminho para um elemento.

jsx
import { BrowserRouter, Routes, Route } from 'react-router-dom'

export default function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </BrowserRouter>
  )
}

Internamente, BrowserRouter é um provedor de contexto. Envolver o app com ele dá a cada componente abaixo acesso às ferramentas do router, que é por que fica no topo. Alguns codebases o renomeiam na importação (import { BrowserRouter as Router }) já que o nome completo é um bocado.

Cada Route recebe duas props. path é a parte da URL após o domínio: / para a página inicial, /about para a página sobre. element é o JSX a renderizar quando a URL corresponde àquele caminho, escrito como um elemento de verdade, <Home /> em vez de Home. Quando a URL é /about, React Router renderiza <About /> onde o componente Routes fica; tudo fora de Routes renderiza em toda página.

Visite um caminho sem rota correspondente e nada renderiza. Essa lacuna é arrumada pela rota coringa abaixo.

A forma HTML de se mover entre páginas é uma tag âncora, e é exatamente errada para uma SPA: clicar em um <a href="/about"> dispara um carregamento de página completo, que descarta o app em execução e cada pedaço de state nele. A resposta do React Router é o componente Link.

jsx
import { Link } from 'react-router-dom'

function Header() {
  return (
    <nav>
      <Link to="/">Home</Link>
      <Link to="/about">About</Link>
    </nav>
  )
}

Link recebe uma prop to em vez de href, e lê de forma natural: um link para a rota seguinte. No navegador ainda renderiza uma tag âncora de verdade, então leitores de tela, menus de clique-direito e seus seletores CSS de elemento veem um <a> comum. A diferença é o handler de clique: React Router intercepta o clique, atualiza a URL e troca os componentes renderizados, tudo sem recarregar o documento. Um contador em dez permanece em dez conforme você se move entre páginas. Dentro de um app React Router, navegação interna sempre passa por Link; âncoras simples são para URLs externas.

Barras de navegação geralmente destacam a página em que você está atualmente. NavLink existe para isso: se comporta como Link, exceto que suas props className e style podem receber uma função em vez de um valor simples. React Router chama essa função com um objeto contendo um booleano isActive, verdadeiro quando a rota do link corresponde à URL atual. Este é o padrão render props, coberto em Render props, aplicado a uma prop diferente de children.

jsx
import { NavLink } from 'react-router-dom'

function Header() {
  return (
    <nav>
      <NavLink
        to="/about"
        className={({ isActive }) => isActive ? 'active-link' : ''}
      >
        About
      </NavLink>
    </nav>
  )
}

Tudo que a função retorna se torna o nome da classe, então a classe active-link se aplica apenas enquanto /about é a rota atual, e seu CSS cuida do resto. A prop style funciona da mesma forma com um objeto de estilo inline:

jsx
const activeStyles = { fontWeight: 'bold', textDecoration: 'underline' }

<NavLink
  to="/about"
  style={({ isActive }) => isActive ? activeStyles : null}
>
  About
</NavLink>

Nome de classe ou estilo inline é uma decisão de convenção de time; ambos são totalmente suportados, então siga o que o projeto já faz.

Uma rota coringa 404

Usuários chegam em caminhos que não existem: um link desatualizado, um erro de digitação, uma referência quebrada de outro. Sem um fallback, React Router renderiza nada lá. A solução é uma rota coringa, às vezes chamada rota splat, cujo caminho é um único asterisco.

jsx
<Routes>
  <Route path="/" element={<Home />} />
  <Route path="/about" element={<About />} />
  <Route path="*" element={<NotFound />} />
</Routes>

path="*" corresponde a qualquer coisa que nenhuma outra rota reivindica, muito como um seletor universal em CSS. Um componente NotFound típico emparelha uma mensagem breve com um Link de volta à página inicial. A ordem na lista não importa: React Router 6 pontua cada rota contra a URL e escolhe a melhor correspondência, então o coringa só vence quando nada mais específico faz. Colocá-lo por último é convenção e legibilidade em vez de necessidade.

O mecanismo por trás de tudo isso é a History API do navegador. Link chama event.preventDefault() em um clique simples à esquerda, empurra a nova URL com history.pushState, e deixa o context provider do router notificar inscritos que a localização mudou. Rotas correspondentes se renderizam; o documento nunca recarrega. Essa também é a história completa de por que state sobrevive: o ambiente JavaScript nunca é desmantelado.

A correspondência de rota em v6 é baseada em ranking. Cada segmento de caminho ganha uma pontuação, com segmentos estáticos vencendo os dinâmicos e dinâmicos vencendo o coringa, então a ordem de definição não tem significado. Isso substituiu o modelo primeiro-vence de v5, onde um / desprotegido no topo da lista obscurecia tudo abaixo.

NavLink conta ancestrais como ativos

O router considera todo ancestral da URL atual como correspondido, então um link para /host relata isActive enquanto você está em /host/income. Normalmente é o que você quer em uma barra de nav. Quando não é, a prop end diz àquele link para corresponder apenas seu caminho exato. Isso importa mais com rotas aninhadas, onde várias rotas renderizam simultaneamente por design.

Roteamento no lado do cliente também tem um detalhe de deployment. BrowserRouter produz URLs limpas como /about, mas o servidor nunca ouviu falar daquele caminho; apenas o router conhece. Um usuário que recarrega ou deep-linka lá atinge o servidor diretamente, então o host deve ser configurado para servir index.html para toda rota e deixar React Router tomar conta da URL. A maioria dos hosts estáticos tem uma regra de rewrite de uma linha para exatamente isso.

A configuração do servidor também é onde o modo framework de v7 muda o cenário. Modo declarativo e modo de dados deixam a build e o servidor para você, enquanto modo framework toma ambos com um plugin Vite que lida com renderização no servidor. Tudo neste capítulo fica no lado declarativo dessa linha.

JunoA URL escolhe os componentes Um app de página única carrega um documento e depois troca o que você vê conforme clica, então não há tremulejo e nada é descartado.

Envolva seu app em BrowserRouter, liste suas páginas como componentes Route dentro de Routes, e cada path recebe seu próprio element para renderizar.

Use Link em vez de uma tag âncora para que clicar mantenha o app em execução, e adicione uma rota path="*" para que visitantes que digitarem mal uma URL vejam uma página amigável em vez de uma tela em branco.

JunoA URL escolhe os componentes O conjunto de trabalho é pequeno: BrowserRouter no topo, Routes contendo elementos Route que mapeiam path para element, Link to para navegação, e NavLink quando a barra de nav deve destacar a página atual.

Passe className ou style uma função e leia isActive do objeto que ela recebe.

Termine a configuração com um coringa path="*" para uma página 404; ranking de rota significa que sua posição na lista é irrelevante.

JunoA URL escolhe os componentesLink previne o clique padrão e impulsiona history.pushState, e BrowserRouter é um provedor de contexto transmitindo mudanças de localização, que é por que state sobrevive à navegação.

Correspondência é baseada em ranking em vez de ordem, ancestrais contam como ativos para NavLink até você adicionar end, e URLs limpas requerem que o servidor reescreva todo caminho para o shell do app.

As APIs de modo declarativo aqui levam direto para v7, que também documenta modo de dados para loaders e actions e modo framework para integração full-stack.

Próximo: Rotas aninhadas e layouts, onde rotas ganham chrome compartilhado e rotas dentro de rotas.