Português

Explore padrões de navegação essenciais com o React Router v6. Aprenda sobre roteamento declarativo, rotas dinâmicas, navegação programática, rotas aninhadas e estratégias de carregamento de dados para construir aplicações web robustas e amigáveis.

React Router v6: Dominando Padrões de Navegação para Aplicações Web Modernas

O React Router v6 é uma biblioteca de roteamento poderosa e flexível para aplicações React. Ele permite que você crie aplicações de página única (SPAs) com uma experiência de usuário fluida, gerenciando a navegação sem recargas completas da página. Este post de blog irá aprofundar-se nos padrões de navegação essenciais usando o React Router v6, fornecendo o conhecimento e os exemplos para construir aplicações web robustas e amigáveis.

Entendendo os Conceitos Fundamentais do React Router v6

Antes de mergulhar em padrões específicos, vamos rever alguns conceitos fundamentais:

1. Roteamento Declarativo com <Routes> e <Route>

A base do React Router v6 está no roteamento declarativo. Você define suas rotas usando os componentes <Routes> e <Route>. O componente <Routes> atua como um contêiner para suas rotas, e o componente <Route> define uma rota específica e o componente a ser renderizado quando essa rota corresponde à URL atual.

Exemplo: Configuração Básica de Rotas

Aqui está um exemplo básico de configuração de rotas para uma aplicação simples:


import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import Contact from "./pages/Contact";

function App() {
  return (
    
      
        } />
        } />
        } />
      
    
  );
}

export default App;

Neste exemplo, definimos três rotas:

O componente BrowserRouter habilita o roteamento baseado no histórico do navegador. O React Router compara a URL atual com as rotas definidas e renderiza o componente correspondente.

2. Rotas Dinâmicas com Parâmetros de URL

Rotas dinâmicas permitem criar rotas que podem lidar com diferentes valores na URL. Isso é útil para exibir conteúdo com base em um identificador único, como o ID de um produto ou de um usuário. O React Router v6 usa o símbolo : para definir parâmetros de URL.

Exemplo: Exibindo Detalhes do Produto

Digamos que você tenha uma aplicação de e-commerce e queira exibir os detalhes de cada produto com base em seu ID. Você pode definir uma rota dinâmica como esta:


import { BrowserRouter, Routes, Route, useParams } from "react-router-dom";

function ProductDetails() {
  const { productId } = useParams();

  // Fetch product details based on productId
  // ...

  return (
    

Product Details

Product ID: {productId}

{/* Display product details here */}
); } function App() { return ( } /> ); } export default App;

Neste exemplo:

Exemplo de Internacionalização: Lidando com Códigos de Idioma

Para um site multilíngue, você pode usar uma rota dinâmica para lidar com códigos de idioma:


} />

Esta rota corresponderia a URLs como /en/about, /fr/about e /es/about. O parâmetro lang pode então ser usado para carregar os recursos de idioma apropriados.

3. Navegação Programática com useNavigate

Embora o roteamento declarativo seja ótimo para links estáticos, muitas vezes você precisa navegar programaticamente com base em ações do usuário ou na lógica da aplicação. O React Router v6 fornece o hook useNavigate para esse propósito. O useNavigate retorna uma função que permite navegar para diferentes rotas.

Exemplo: Redirecionando Após o Envio de um Formulário

Digamos que você tenha um envio de formulário e queira redirecionar o usuário para uma página de sucesso após o envio bem-sucedido:


import { useNavigate } from "react-router-dom";

function MyForm() {
  const navigate = useNavigate();

  const handleSubmit = async (event) => {
    event.preventDefault();

    // Submit the form data
    // ...

    // Redirect to the success page after successful submission
    navigate("/success");
  };

  return (
    
{/* Form fields */}
); } export default MyForm;

Neste exemplo:

Passando Estado Durante a Navegação

Você também pode passar estado junto com a navegação usando o segundo argumento de navigate:


navigate("/confirmation", { state: { orderId: "12345" } });

Isso permite que você passe dados para o componente de destino, que podem ser acessados usando o hook useLocation.

4. Rotas Aninhadas e Layouts

Rotas aninhadas permitem criar estruturas de roteamento hierárquicas, onde uma rota está aninhada dentro de outra. Isso é útil para organizar aplicações complexas com múltiplos níveis de navegação. Isso ajuda na criação de layouts onde certos elementos de UI estão consistentemente presentes em uma seção da aplicação.

Exemplo: Seção de Perfil de Usuário

Digamos que você tenha uma seção de perfil de usuário com rotas aninhadas para exibir as informações do perfil do usuário, configurações e pedidos:


import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

function Profile() {
  return (
    

Perfil de Usuário

  • Informações do Perfil
  • Configurações
  • Pedidos
} /> } /> } />
); } function ProfileInformation() { return

Componente de Informações do Perfil

; } function Settings() { return

Componente de Configurações

; } function Orders() { return

Componente de Pedidos

; } function App() { return ( } /> ); } export default App;

Neste exemplo:

O * na rota pai é crucial; ele significa que a rota pai deve corresponder a qualquer sub-caminho, permitindo que as rotas aninhadas sejam correspondidas corretamente dentro do componente Profile.

5. Lidando com Erros "Não Encontrado" (404)

É essencial lidar com casos em que o usuário navega para uma rota que não existe. O React Router v6 facilita isso com uma rota "catch-all" (pega-tudo).

Exemplo: Implementando uma Página 404


import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

function NotFound() {
  return (
    

404 - Não Encontrado

A página que você está procurando não existe.

Voltar para a página inicial
); } function App() { return ( } /> } /> } /> ); }

Neste exemplo:

6. Estratégias de Carregamento de Dados com o React Router v6

O React Router v6 não inclui mecanismos de carregamento de dados integrados como seu antecessor (React Router v5 com `useRouteMatch`). No entanto, ele fornece as ferramentas para implementar várias estratégias de carregamento de dados de forma eficaz.

Opção 1: Buscando Dados nos Componentes

A abordagem mais simples é buscar dados diretamente no componente que renderiza a rota. Você pode usar o hook useEffect para buscar dados quando o componente é montado ou quando os parâmetros da URL mudam.


import { useParams } from "react-router-dom";
import { useEffect, useState } from "react";

function ProductDetails() {
  const { productId } = useParams();
  const [product, setProduct] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchProduct() {
      try {
        const response = await fetch(`/api/products/${productId}`);
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        const data = await response.json();
        setProduct(data);
        setLoading(false);
      } catch (e) {
        setError(e);
        setLoading(false);
      }
    }

    fetchProduct();
  }, [productId]);

  if (loading) return 

Carregando...

; if (error) return

Erro: {error.message}

; if (!product) return

Produto não encontrado

; return (

{product.name}

{product.description}

); } export default ProductDetails;

Esta abordagem é direta, mas pode levar à duplicação de código se você precisar buscar dados em vários componentes. Também é menos eficiente porque a busca de dados começa apenas depois que o componente é montado.

Opção 2: Usando um Hook Personalizado para Busca de Dados

Para reduzir a duplicação de código, você pode criar um hook personalizado que encapsula a lógica de busca de dados. Este hook pode então ser reutilizado em múltiplos componentes.


import { useState, useEffect } from "react";

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchData() {
      try {
        const response = await fetch(url);
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        const json = await response.json();
        setData(json);
        setLoading(false);
      } catch (e) {
        setError(e);
        setLoading(false);
      }
    }

    fetchData();
  }, [url]);

  return { data, loading, error };
}

export default useFetch;

Então, você pode usar este hook em seus componentes:


import { useParams } from "react-router-dom";
import useFetch from "./useFetch";

function ProductDetails() {
  const { productId } = useParams();
  const { data: product, loading, error } = useFetch(`/api/products/${productId}`);

  if (loading) return 

Carregando...

; if (error) return

Erro: {error.message}

; if (!product) return

Produto não encontrado

; return (

{product.name}

{product.description}

); } export default ProductDetails;

Opção 3: Usando uma Biblioteca de Roteamento com Capacidades de Busca de Dados (TanStack Router, Remix)

Bibliotecas como TanStack Router e Remix oferecem mecanismos de busca de dados integrados que se integram perfeitamente com o roteamento. Essas bibliotecas geralmente fornecem recursos como:

Usar uma biblioteca como essa pode simplificar drasticamente o carregamento de dados e melhorar o desempenho, especialmente para aplicações complexas.

Renderização no Lado do Servidor (SSR) e Geração de Site Estático (SSG)

Para melhorar o SEO e o desempenho do carregamento inicial, considere o uso de SSR ou SSG com frameworks como Next.js ou Gatsby. Esses frameworks permitem que você busque dados no servidor ou durante o tempo de construção e sirva HTML pré-renderizado para o cliente. Isso elimina a necessidade de o cliente buscar dados no carregamento inicial, resultando em uma experiência mais rápida e amigável para SEO.

7. Trabalhando com Diferentes Tipos de Router

O React Router v6 fornece diferentes implementações de router para se adequar a vários ambientes e casos de uso:

Escolha o tipo de router que melhor se adapta aos requisitos e ao ambiente da sua aplicação.

Conclusão

O React Router v6 fornece uma solução de roteamento abrangente e flexível para aplicações React. Ao entender e aplicar os padrões de navegação discutidos neste post de blog, você pode construir aplicações web robustas, amigáveis e de fácil manutenção. Desde o roteamento declarativo com <Routes> e <Route> até rotas dinâmicas com parâmetros de URL, navegação programática com useNavigate e estratégias eficazes de carregamento de dados, o React Router v6 capacita você a criar experiências de navegação fluidas para seus usuários. Considere explorar bibliotecas de roteamento avançadas e frameworks SSR/SSG para um controle e otimização de desempenho ainda maiores. Lembre-se de adaptar esses padrões aos requisitos específicos da sua aplicação e sempre priorizar uma experiência de usuário clara e intuitiva.

React Router v6: Dominando Padrões de Navegação para Aplicações Web Modernas | MLOG