🛣O Guia Definitivo sobre Rotas com React Router
Tags: react, javascript, webdev, beginners
Published: 2023-02-02 01:47:49

Rotas em React são responsáveis por determinar como os usuários navegam pelo seu aplicativo. Quando um usuário clica em um link ou digita uma URL, a rota controla qual página do aplicativo será exibida para o usuário. Por exemplo, se você estiver desenvolvendo um aplicativo de compras on-line, poderá ter uma rota para a página inicial, uma rota para a página de categorias, uma rota para a página de produtos, uma rota para a página de carrinho de compras, etc.

Ter uma estrutura de rotas clara e fácil de entender é importante porque ajuda a melhorar a navegação e a experiência do usuário. Além disso, também pode ajudar a proteger certas páginas de acesso não autorizado e garantir que o usuário seja redirecionado para a página correta após realizar determinadas ações.

Felizmente, a biblioteca React Router facilita a criação de uma estrutura de rotas clara e organizada em um aplicativo React. A seguir, veremos como configurar e usar o React Router para criar uma estrutura de rotas eficiente em seu aplicativo React.

Neste guia, você verá:
 * [ Instalação do React Router](#instala%C3%A7%C3%A3o-do-react-router)  
 * [ Componentes Básicos do React Router](#componentes-b%C3%A1sicos-do-react-router)  
 * [ Hooks Básicos do React Router](#hooks-b%C3%A1sicos-do-react-router)  
 * [ Conceitos Adicionais sobre Rotas](#conceitos-adicionais-sobre-rotas)  
 * [ Rotas Exatas](#rotas-exatas)  
 * [ Rotas Simples](#rotas-simples)  
 * [ Parâmetros de Rotas](#par%C3%A2metros-de-rotas)  
 * [ Tópicos Avançados em React Router](#t%C3%B3picos-avan%C3%A7ados-em-react-router)  
 * [ Proteção de Rotas](#prote%C3%A7%C3%A3o-de-rotas)  
 * [ Query Strings](#query-strings)  
 * [ Lidando com Query Strings no React Router V6+](#lidando-com-query-strings-no-react-router-v6)  
 * [ Considerações Finais](#considera%C3%A7%C3%B5es-finais) 

---

## Instalação do React Router

Há duas maneiras de instalar o React Router: usando npm ou yarn.

Se você estiver usando npm, pode instalar o React Router digitando o seguinte comando no terminal:
```javascript
npm install react-router-dom
```

Se você estiver usando yarn, pode instalar o React Router digitando o seguinte comando no terminal:

```javascript
yarn add react-router-dom
```

Agora que o React Router está instalado, podemos começar a configurá-lo.

---

## Componentes Básicos do React Router

Tomando-se como referência a última versão da biblioteca React Router nesta data ([v6.8.0](https://reactrouter.com/en/main)), os principais componentes são:
<br>

- **BrowserRouter**: O `BrowserRouter` é usado para fornecer a funcionalidade de roteamento ao seu aplicativo React. Ele é responsável por gerenciar as mudanças de URL e rotas na página do seu aplicativo. Quando o usuário clica em um link ou digita uma URL na barra de endereços do navegador, o BrowserRouter detecta essa mudança e faz a renderização da página correta de acordo com a rota definida.
<br>

- **Routes**: O componente `Routes` do React Router é usado para gerenciar as rotas da aplicação. Ele é responsável por renderizar o componente correto para a URL atual da página. O componente `Routes` precisa ser envolvido por um componente do React Router, como o `BrowserRouter` ou `MemoryRouter`, para funcionar.
<br>

- **Route**: O componente `Route` é um dos componentes-chave do React Router. Ele é usado para criar rotas na sua aplicação, determinando quais componentes serão renderizados para cada URL específica.

Vejamos um exemplo de como os componentes `BrowserRouter`, `Routes` e `Route` podem ser usados na prática:

```javascript
import React from 'react';
// Importamos o componente BrowserRouter e o componente Routes do pacote react-router-dom
import { BrowserRouter, Routes, Route } from 'react-router-dom';

// Importamos as páginas HomePage, AboutPage e ContactPage
import HomePage from './pages/HomePage';
import AboutPage from './pages/AboutPage';
import ContactPage from './pages/ContactPage';

// Função principal do componente App
function App() {
  return (
    // Envolve o componente App com o componente BrowserRouter
    <BrowserRouter>
      {/* O componente Routes permite que você crie várias rotas que são renderizadas com base na URL atual */}
      <Routes>
        {/* Adiciona uma rota com o caminho exato "/", que renderiza o componente HomePage */}
        <Route path="/" element={<HomePage />} />
        {/* Adiciona uma rota com o caminho "/about", que renderiza o componente AboutPage */}
        <Route path="/about" element={<AboutPage />} />
        {/* Adiciona uma rota com o caminho "/contact", que renderiza o componente ContactPage */}
        <Route path="/contact" element={<ContactPage />} />
      </Routes>
    </BrowserRouter>
  );
}

// Exporta o componente App como padrão
export default App;
```

O código acima é uma aplicação React que usa o React Router para gerenciar as rotas em seu aplicativo. Aqui está uma explicação passo a passo do código:

1 - Importamos as dependências necessárias para usar o React Router. Primeiro, importamos o componente `BrowserRouter` e o componente `Routes` do pacote `react-router-dom`.

2 - Em seguida, importamos as páginas `HomePage`, `AboutPage` e `ContactPage`. Essas são as três páginas diferentes que nossa aplicação irá exibir, dependendo da rota atual.

3 - Definimos a função `App`, que é o componente principal da nossa aplicação. Dentro dessa função, usamos o componente `BrowserRouter`como envoltório para o resto da aplicação.

4 - Dentro do componente `BrowserRouter`, usamos o componente `Routes`para gerenciar as rotas em nossa aplicação. O componente `Routes` permite que você crie várias rotas que são renderizadas com base na URL
atual.

5 - Em seguida, usamos o componente `Route` para adicionar três rotas diferentes à nossa aplicação. Cada rota é definida com uma propriedade `path` que indica a URL a ser exibida e uma propriedade `element` que indica o componente a ser renderizado para aquela URL. A primeira rota tem o caminho exato `/`, que renderiza o componente `HomePage`. A segunda rota tem o caminho `/about`, que renderiza o componente `AboutPage`. A terceira rota tem o caminho `/contact`, que renderiza o componente `ContactPage`.

6 - Finalmente, exportamos o componente `App` como padrão, permitindo que seja usado em outros arquivos da aplicação.
<br>

- **Switch**: O `Switch` é um componente do React Router que permite que você selecione apenas uma rota para ser renderizada dentre várias rotas definidas. Isso é útil quando você tem várias rotas que compartilham um prefixo comum na URL, mas deseja mostrar apenas uma dessas rotas.
Aqui está um exemplo de código:
```javascript
import { Switch, Route } from 'react-router-dom';

function App() {
  return (
    <Switch>
      {/* A rota "/" será renderizada se a URL atual for "/" */}
      <Route exact path="/">
        <Home />
      </Route>
      {/* A rota "/about" será renderizada se a URL atual for "/about" */}
      <Route path="/about">
        <About />
      </Route>
      {/* Esta é a rota "padrão" que será renderizada se nenhuma das rotas acima for combinar com a URL atual */}
      <Route path="*">
        <NotFound />
      </Route>
    </Switch>
  );
}
```

Neste exemplo, usamos o componente `Switch` para envolver nossas rotas.

Dentro dele, usamos o componente `Route` para definir as rotas diferentes que o aplicativo pode ter. A propriedade `exact` em `<Route exact path="/">` significa que a rota só será renderizada se a URL atual for exatamente `/`. Se omitirmos `exact`, a rota seria renderizada para todas as URLs que começarem com `/`, como `/about`. 

Finalmente, a rota `<Route path="*">` é a rota padrão que será renderizada se nenhuma das outras rotas combinar com a URL atual.

Quando o usuário navega no aplicativo, o endereço da URL mudará de acordo com a página em que o usuário está. O React Router usa essa URL para determinar qual rota deve ser renderizada.

Se nenhuma das rotas definidas dentro do `Switch` combinar com a URL atual, a rota padrão será renderizada. Por exemplo, se o usuário estiver na URL `/invalid`, nenhuma das rotas definidas dentro do `Switch` combinará com esta URL. Neste caso, a rota `<Route path="*">` será renderizada, mostrando o componente `NotFound`.

Em outras palavras, o `Switch` ajuda a garantir que apenas uma rota seja renderizada a qualquer momento, dependendo da URL atual.
<br>

- **Link**: O componente `Link` do React Router é uma forma simples de criar links para outras páginas em seu aplicativo. Em vez de usar um elemento `a` normal para navegar entre páginas, você usa o componente `Link`, que fornece algumas vantagens, como manter o histórico do navegador e evitar recarregar a página inteira.

Aqui está um exemplo de código para criar um link para a página inicial de seu aplicativo:

```javascript
import { Link } from 'react-router-dom';

function HomeLink() {
  return (
    <Link to="/">
      Home
    </Link>
  );
}
```

Neste exemplo, estamos importando o componente `Link` do pacote `reactrouter-dom`. Em seguida, criamos uma função `HomeLink` que retorna um componente `Link`. O atributo `to` é usado para especificar a URL para a qual o link deve levar. Finalmente, dentro do componente `Link`, colocamos o texto que será exibido como link na página.
<br>

- **NavLink**: O `NavLink` é um componente do React Router que permite a criação de links para outras páginas ou rotas em sua aplicação. Ele funciona de forma similar ao elemento HTML `<a>`, mas com algumas vantagens extras, como a capacidade de ativar estilos específicos quando o usuário está na página associada ao link. o `NavLink` é frequentemente usado em menus, como navbars.

Aqui está um exemplo de como você pode usar o `NavLink` em um componente de menu navbar:

```javascript
import React from "react";
import { NavLink } from "react-router-dom";

function Navbar() {
  return (
    <nav>
      <ul>
        <li>
          {/* Cria o link Home */}
          <NavLink 
            exact 
            to="/" 
            activeClassName="selected">
            Home
          </NavLink>
        </li>
        <li>
          {/* Cria o link About */}
          <NavLink 
            to="/about" 
            activeClassName="selected">
            About
          </NavLink>
        </li>
        <li>
          {/* Cria o link Contact */}
          <NavLink 
            to="/contact" 
            activeClassName="selected">
            Contact
          </NavLink>
        </li>
      </ul>
    </nav>
  );
}

export default Navbar;
```
Este código cria um componente React chamado `Navbar` que renderiza um menu de navegação. O componente usa o `NavLink` do React Router para criar links para diferentes páginas na aplicação.

A estrutura básica do componente é uma `<nav>` que contém uma lista `<ul>` com três itens de menu, cada um contendo um link. Cada link é criado usando o componente `NavLink`, especificando a URL a ser navegada quando o usuário clicar no link com a propriedade `to`. 

A propriedade `exact` especifica que o link deve ser uma correspondência exata com a URL, ou seja, apenas a página inicial corresponderá exatamente à URL raiz (`/`).

A propriedade `activeClassName` especifica o nome da classe CSS que será aplicada ao link quando o usuário estiver na página associada ao link.

Neste exemplo, a classe `selected` será aplicada.

Por fim, o componente é exportado como `default` para ser usado em outros lugares da aplicação.
<br> 

- **Navigate**: O componente `Navigate` do React Router é usado para navegar entre as rotas em uma aplicação React. É uma maneira simples de mudar de página sem precisar atualizar a página inteira. Em vez disso, ele apenas atualiza a parte da página que é exibida na rota atual.

Aqui está um exemplo de código que mostra como usar o `Navigate` para navegar de uma página para outra:

```javascript
import { Navigate } from "react-router-dom";

function Example() {
  return (
    <div>
      {/* Exibe o título da página atual */}
      <h1>Minha página atual</h1>
      <button>
        {/* Usa o componente Navigate para navegar para a rota "/outra-página" */}
        <Navigate to="/outra-pagina">Ir para outra página</Navigate>
      </button>
    </div>
  );
}
```
Neste exemplo, estamos importando o componente `Navigate` do pacote `react-router-dom`. Em seguida, estamos criando uma função `Example` que retorna um elemento `div` com um cabeçalho e um botão.

Quando o usuário clicar no botão, o componente `Navigate` será acionado e a rota será alterada para `/outra-pagina`. Isso significa que a página será atualizada com o conteúdo da nova rota, sem atualizar a página inteira.

Estes foram apenas alguns dos componentes básicos mais utilizados da biblioteca React Router. Não deixe de acessar os documentos oficiais para conhecer os demais componentes e suas funcionalidades: [https://reactrouter.com/en/main](https://reactrouter.com/en/main)

---

## Hooks Básicos do React Router

Agora, exploraremos alguns dos hooks mais populares da biblioteca React Router e como eles podem ser usados para melhorar a funcionalidade e a experiência do usuário em sua aplicação.

Hooks são uma funcionalidade no React que permitem que você compartilhe lógica de estado entre componentes sem ter que escrever componentes de classe. No React Router, os hooks permitem que você acesse e manipule informações da rota em sua aplicação, como a URL atual, o histórico de navegação e os parâmetros da rota. Eles são uma maneira fácil e poderosa de adicionar funcionalidade à sua aplicação.

Quando se trata de definir rotas em sua aplicação, é importante escolher a abordagem certa para atender às suas necessidades. Você pode usar um componente como `Route` ou `Switch` para definir rotas, ou pode usar um hook como `useRoutes` para renderizar rotas condicionalmente. A escolha entre um componente e um hook depende da complexidade de suas rotas e da funcionalidade que você precisa adicionar à sua aplicação. Abaixo, vamos explorá-los em detalhes.
<br>

- **useRoutes**: O hook `useRoutes` do React Router é usado para renderizar rotas condicionalmente com base nas condições fornecidas. É uma alternativa ao uso de `Route` e `Switch` para definir rotas em sua aplicação.

Aqui está um exemplo de como usar o hook `useRoutes`:
```javascript
import { useRoutes } from "react-router-dom";

const routes = [
  // Rota para a página inicial
  {
    path: "/",
    element: <Home />
  },
  // Rota para a página de login
  {
    path: "/login",
    element: <Login />
  },
  // Rota condicional para o dashboard
  {
    path: /^\/dashboard/,
    element: isLoggedIn ? <Dashboard /> : <Redirect to="/login" />
  }
];

function App() {
  // Obtém o resultado da rota atual
  const routeResult = useRoutes(routes);

  // Renderiza o resultado da rota atual
  return <div>{routeResult}</div>;
}
```
Neste exemplo, o hook `useRoutes` é usado para renderizar diferentes componentes dependendo da URL atual. Temos três rotas definidas em `routes`: uma para a página inicial (`"/"`), uma para a página de login (`"/login"`) e uma para o dashboard (`"/dashboard"`).

A rota para o dashbaord é condicional: se a variável `isLoggedIn` for verdadeira, o usuário será redirecionado para o dashboard, caso contrário, será redirecionado para a página de login.

O resultado do hook `useRoutes` é atribuído à variável `routeResult` e, em seguida, renderizado na tela usando `{routeResult}`.

Este exemplo mostra como o hook `useRoutes` pode ser usado para adicionar funcionalidade condicional à sua aplicação, permitindo que você defina rotas de maneira fácil e eficiente.
<br>

- **useParams**: O hook `useParams` é um hook do React Router que permite acessar os parâmetros da URL da rota atual. Ele retorna um objeto que contém as chaves e valores dos parâmetros da URL.

Por exemplo, se você tiver uma rota com a URL `/users/:id`, você pode usar o hook `useParams` para acessar o valor do ID do usuário.

Veja abaixo um exemplo de como usar o hook `useParams`:
```javascript
import { useParams } from 'react-router-dom';

function UserDetail() {
  // Usa o hook useParams para acessar os parâmetros da URL
  const { id } = useParams();

  return (
    <div>
      <h1>Detalhes do usuário {id}</h1>
    </div>
  );
}
```
A primeira linha importa o hook `useParams` do pacote `react-router-dom`.

A função `UserDetail` é um componente React que será renderizado quando a URL da rota corresponder a uma rota que inclui um parâmetro, como `/usuarios/:id`.

Dentro da função `UserDetail`, o hook `useParams` é chamado usando `const { id } = useParams()`. Este hook retorna um objeto que contém as chaves e valores dos parâmetros da URL. No caso deste exemplo, o objeto terá uma chave `id` e um valor que corresponde ao ID do usuário passado na URL.

O componente `UserDetail` renderiza um elemento `div` que contém um cabeçalho `h1` que exibe o texto "Detalhes do usuário" seguido pelo valor do ID do usuário acessado pelo hook `useParams`.

Por exemplo, se a URL da rota for `/usuarios/123`, o componente `UserDetail` renderizará o seguinte HTML:
```javascript
<div>
  <h1>Detalhes do usuário 123</h1>
</div>
```

<br>
- **useLocation**: O hook `useLocation` permite que você acesse informações sobre a URL atualmente exibida no navegador. É uma forma de ter informações sobre a rota que o usuário está visualizando no momento.

Vejamos um exemplo de como ele pode ser útil:
```javascript
import { useLocation } from 'react-router-dom';

function ScrollToTopOnMount() {
  const { pathname } = useLocation();

  // sempre que a rota muda, faça o scroll da página para o topo
  useEffect(() => {
    window.scrollTo(0, 0);
  }, [pathname]);

  return null;
}
```
Neste exemplo, estamos usando `useLocation` para acessar o `pathname` da rota atual. Quando o `pathname` muda, o `useEffect` é executado e faz o scroll da página para o topo. Isso garante que ao mudar de rota, o usuário sempre comece vendo o topo da página, independentemente de onde estivesse na página anterior.

Outro exemplo importante para entendermos o `useLocation` no React Router seria:
```javascript
import { useLocation } from 'react-router-dom';

function HighlightActiveNavLink() {
  // Acessa informações sobre a URL atual usando o hook useLocation
  const location = useLocation();

  return (
    <nav>
      <ul>
        <li className={location.pathname === '/' ? 'active' : ''}>
          <Link to="/">Home</Link>
        </li>
        <li className={location.pathname === '/about' ? 'active' : ''}>
          <Link to="/about">About</Link>
        </li>
        <li className={location.pathname === '/contact' ? 'active' : ''}>
          <Link to="/contact">Contact</Link>
        </li>
      </ul>
    </nav>
  );
}
```
Aqui, estamos usando o hook `useLocation` para acessar informações sobre a URL atual. Em seguida, estamos comparando o valor da propriedade `pathname` da variável `location` com diferentes rotas para verificar qual deles é a rota atual. Finalmente, estamos adicionando uma classe `active` ao item de menu correto para destacá-lo visualmente como o link ativo.
<br>

- **useNavigate**: O hook `useNavigate` é usado no React Router para navegar programaticamente entre as rotas de uma aplicação. Em vez de clicar em um link para mudar de página, você pode usar o hook `useNavigate` para mudar de página a partir de um componente.

Por exemplo, imagine que você tenha um formulário de contato em sua aplicação e, após o usuário enviar o formulário, você gostaria de redirecioná-lo para uma página de agradecimento:
```javascript
import { useNavigate } from 'react-router-dom';

function ContactForm() {
  // Importa o hook `useNavigate` para poder navegar para outras páginas
  const navigate = useNavigate();

  const handleSubmit = event => {
    event.preventDefault();
    // Aqui você pode adicionar a lógica para enviar o formulário ao seu back-end
    // ...

    // Depois de enviar o formulário com sucesso, navegue para a página de agradecimento
    navigate('/obrigado');
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* Seu formulário de contato aqui */}
      <button type="submit">Enviar</button>
    </form>
  );
}
```
Neste exemplo, usamos o hook `useNavigate` para importar a função `navigate`. Em seguida, quando o usuário submete o formulário, chamamos a função `navigate` e passamos a URL para a página de agradecimento, que é `'/obrigado'` neste exemplo.

Isso fará com que o usuário seja redirecionado para a página de agradecimento após o envio bem-sucedido do formulário.
<br>

- **useHistory**: O hook `useHistory` do React Router nos permite ter acesso ao objeto `history` da nossa aplicação, o que significa que podemos navegar para diferentes páginas sem precisar usar links ou botões. Esse hook é muito útil quando queremos navegar para outra página de forma programática, ou seja, a partir de uma ação do usuário ou de algum evento.

Vamos ver um exemplo de como podemos utilizar o `useHistory` para navegar para uma página de detalhes a partir de um componente de listagem:
```javascript
import React from 'react';
import { useHistory } from 'react-router-dom';

function ProductList() {
  // Acessamos o objeto history com o hook useHistory
  const history = useHistory();

  function handleClick(id) {
    // Usamos o método push do objeto history para navegar para outra página
    history.push(`/products/${id}`);
  }

  return (
    <ul>
      <li onClick={() => handleClick(1)}>Produto 1</li>
      <li onClick={() => handleClick(2)}>Produto 2</li>
      <li onClick={() => handleClick(3)}>Produto 3</li>
    </ul>
  );
}
```
Aqui, o hook `useHistory` é usado para acessar o objeto `history`, que permite navegar entre as páginas da aplicação.

1 - Primeiramente, importamos o hook `useHistory` do pacote `react-router-dom`.

2 - Em seguida, criamos uma função chamada `ProductList`, que será o nosso componente de lista de produtos.

3 - Dentro desta função, usamos o hook `useHistory` para acessar o objeto `history`.

4 - Criamos uma função chamada `handleClick`, que será chamada quando o usuário clicar em um produto na lista.

5 - A função `handleClick` usa o método `push` do objeto `history` para navegar para a página de detalhes do produto. O método `push` recebe como argumento o caminho da página para onde queremos navegar, no formato `/products/{id}`, onde `{id}` é o ID do produto que o usuário clicou.

6 - Por fim, retornamos uma lista de elementos HTML `li` que representam os produtos. Cada elemento tem um `onClick` que chama a função `handleClick` passando o ID do produto.

Dessa forma, apesar da navegação ser acionada ao clique do usuário, a troca de páginas é mais automatizada, já que o clique no link do produto está sendo tratado dentro do componente, ao invés de ser feito diretamente na página HTML.

Isso significa que é possível colocar lógicas dentro do componente que determinem para onde o usuário deve ser direcionado de acordo com certas condições, antes de redirecioná-lo.

Para compreendermos melhor, vamos ver mais um exemplo no qual o `useHistory` é comumente usado:
```javascript
import React, { useState } from 'react';
import { useHistory } from 'react-router-dom';

function Login() {
  // Acessamos o objeto history com o hook useHistory
  const history = useHistory();

  // Mantemos o estado do formulário de login
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');

  // Função chamada quando o formulário é enviado
  function handleSubmit(event) {
    event.preventDefault();

    // Aqui você pode colocar o código para autenticar o usuário
    // Suponha que o usuário está autenticado
    const isAuthenticated = true;

    if (isAuthenticated) {
      // Navegamos para a página inicial se o usuário for autenticado
      history.push('/');
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={username}
        onChange={(event) => setUsername(event.target.value)}
        placeholder="Nome de usuário"
      />
      <input
        type="password"
        value={password}
        onChange={(event) => setPassword(event.target.value)}
        placeholder="Senha"
      />
      <button type="submit">Entrar</button>
    </form>
  );
}
```
Neste exemplo, quando o usuário preenche o formulário de login e clica no botão `Entrar`, a função `handleSubmit` é chamada. Nela, fazemos a validação de autenticação do usuário (neste caso, supomos que ele está autenticado). 

Se o usuário for autenticado, usamos o método `push` do objeto `history` para navegar para a página inicial (`/`). Dessa forma, a navegação é acionada programaticamente sem a interação do usuário com um link ou botão específico.
<br>

Nós vimos apenas alguns dos hooks disponíveis no React Router, mas há muito mais a ser explorado. Para saber mais sobre os outros hooks e como eles podem ser usados em seus projetos, visite a documentação oficial no link: [https://reactrouter.com/en/main](https://reactrouter.com/en/main)

---

## Conceitos Adicionais sobre Rotas

Agora que já temos uma noção básica dos principais hooks e componentes em rotas de aplicativos React, não podemos deixar de conhecer alguns conceitos essenciais antes de avançarmos.
<br>

### Rotas Exatas

As rotas exatas são aquelas que correspondem exatamente à URL que você especificou. Por exemplo, se você tem uma rota definida como `/sobre`, então somente a URL `/sobre` corresponderá a esta rota. Se alguém acessar `/sobre/mais-informacoes`, ele não será direcionado para esta rota.

Para criar uma rota exata, você pode usar o método `exact` na sua definição de rota:
```javascript
<Route exact path="/sobre" component={AboutPage} />
```
<br>

### Rotas Simples

As rotas simples, por outro lado, são mais flexíveis e podem corresponder a qualquer URL que comece com o padrão que você especificou. Por exemplo, se você tem uma rota definida como `/sobre`, então tanto a URL `/sobre` quanto `/sobre/mais-informacoes` corresponderão a esta rota.

Para criar uma rota simples, você não precisa usar o método `exact`:
```javascript
<Route path="/sobre" component={AboutPage} />
```
<br>

### Parâmetros de Rotas

Às vezes, você pode querer que a sua rota corresponda a uma URL que inclua informações adicionais, como o ID de um usuário ou o nome de um produto. Neste caso, você pode usar parâmetros de rota.

Por exemplo, você pode criar uma rota que corresponda a URL `/produto/:id`, onde `:id` representa um parâmetro que pode ser qualquer valor:
```javascript
<Route path="/produto/:id" component={ProductPage} />
```
Agora, se alguém acessar a URL `/produto/123`, ele será direcionado para a página do produto com ID 123. Você pode acessar o valor desse parâmetro na sua página de destino usando o objeto `props`.

---

# Tópicos Avançados em React Router

Agora que você já possui uma compreensão básica dos componentes, hooks e conceitos do React Router, está na hora de explorar alguns tópicos avançados. Nesta seção, você aprenderá sobre proteção de rotas e como trabalhar com query strings no React Router.

A proteção de rotas é uma funcionalidade importante para garantir que somente usuários autorizados acessem certas áreas de seu aplicativo. Além disso, você também aprenderá sobre query strings, que permitem que você passe informações adicionais na URL. Finalmente, você descobrirá como lidar com query strings no React Router V6+.

Com estes conhecimentos, você estará pronto para construir aplicativos ainda mais avançados e funcionais com o React Router. Vamos começar!
<br>

## Proteção de Rotas

Em algumas situações, queremos restringir o acesso a algumas páginas do aplicativo para usuários não autorizados. Para fazer isso, podemos criar rotas "privadas", por exemplo, usando o recurso "routes" do React Router versão 6 em diante para proteger suas rotas.

Para proteger uma rota, você precisa criar uma função que verifica se o usuário está autenticado e, se não estiver, redireciona-o para uma página de login. Aqui está um exemplo de código de uma função de verificação de autenticação:
```javascript
const isAuthenticated = () => {
  const token = localStorage.getItem("token");
  return token !== null;
};
```

A função `isAuthenticated` verifica se o usuário está autenticado ou não. Ele faz isso verificando se existe um token armazenado no `localStorage` do navegador.

O `localStorage` é uma API de armazenamento de dados que permite armazenar dados no navegador de forma persistente, mesmo depois que a página é fechada. Nesse caso, a função está verificando se existe um item chamado "token" no `localStorage`.

Se o item "token" existir, significa que o usuário está autenticado e a função retorna `true`. Se o item "token" não existir, significa que o usuário não está autenticado e a função retorna `false`.

Em seguida, você pode usar essa função na sua rota para protegê-la. Aqui está um exemplo de como fazer isso:
```javascript
import { navigate } from "@reach/router";

const PrivateRoute = ({ children, ...rest }) => {
  if (!isAuthenticated()) {
    navigate("/login");
    return null;
  }

  return (
    <Route {...rest}>
      {children}
    </Route>
  );
};
```

Este código cria um componente chamado `PrivateRoute` que é usado para proteger rotas na aplicação.

O componente importa a função `navigate` do pacote `@reach/router`. Essa função é usada para navegar para outra rota da aplicação.

A função `PrivateRoute` tem dois parâmetros: `children` e `rest`.

`children` representa o conteúdo da rota protegida e `rest` representa todos os outros parâmetros da rota, como `path`, `exact`, etc.

Dentro da função `PrivateRoute`, há uma verificação se o usuário está autenticado ou não, usando a função `isAuthenticated`. Se o usuário não estiver autenticado, a função `navigate` é usada para navegar para a rota "/login". Nesse caso, a função `PrivateRoute` retorna `null`, o que significa que nenhum conteúdo será renderizado na tela.

Se o usuário estiver autenticado, a função `PrivateRoute` retorna uma `Route` com todos os parâmetros da rota original (`rest`) e o conteúdo da rota protegida (`children`).

Agora, você pode usar o componente "PrivateRoute" em vez de "Route" em sua aplicação para proteger uma rota específica.

Aqui está um exemplo de como fazer isso:
```javascript
import { PrivateRoute } from "./PrivateRoute";

function App() {
  return (
    <Routes>
      <PrivateRoute path="dashboard" element={<Dashboard />} />
      <Route path="login" element={<Login />} />
    </Routes>
  );
}
```

Este código é um exemplo de como usar o componente `PrivateRoute` na sua aplicação.

A função `App` é o componente principal da aplicação. Ela retorna um componente `Routes` com as rotas da aplicação.

Há duas rotas definidas: `dashboard` e `login`. A rota `dashboard` é protegida usando o componente `PrivateRoute`. Isso significa que somente usuários autenticados poderão acessar a rota `dashboard`. Se o usuário não estiver autenticado, será redirecionado para a rota `login`.

A rota `login` não está protegida e pode ser acessada por qualquer usuário, independentemente de seu estado de autenticação.

Em suma, proteger rotas no React Router versão 6 é fácil usando apenas o componente "route" e a função "navigate". Você pode criar um componente personalizado, como "PrivateRoute", para proteger suas rotas e garantir que apenas usuários autenticados tenham acesso a elas.

Alem dessa, existem várias outras maneiras de se criar proteção de rotas com o React Router. Caso queira saber mais, recomendo o artigo [Private Route in react-router v6](https://dev.to/iamandrewluca/private-route-in-react-router-v6-lg5) de André Luca.

---

## Query Strings

Uma query string é uma parte opcional de uma URL que contém informações adicionais para o servidor. Ela é composta por pares de chave-valor separados por caracteres especiais, como "&", ";" ou "?".

A query string é enviada para o servidor como parte da requisição HTTP. O servidor pode usar essas informações para determinar como processar a requisição e retornar uma resposta adequada. Por exemplo, a query string pode fornecer informações de pesquisa, filtros de resultados de pesquisa, preferências de usuário, entre outros.

Por exemplo, na URL "https://twitter.com/search?q=Newcastle&src=trend_click&vertical=trends", as strings "?" e "&" são usadas para separar as informações adicionais na query string da URL.

- A string "?" marca o início da query string. Tudo após o "?" é considerado parte da query string.

- A string "&" é usada para separar diferentes pares de chave-valor na query string. Cada par de chave-valor é separado pelo caractere "&".

- "/search" é o caminho para a página específica dentro do domínio.

- "q=Newcastle" é o primeiro par de chave-valor na query string. "q" é a chave que representa o termo de pesquisa e "Newcastle" é o valor desse termo.

- "src=trend_click" é o segundo par de chave-valor na query string. "src" é a chave e "trend_click" é o valor.

- "vertical=trends" é o terceiro par de chave-valor na query string. "vertical" é a chave e "trends" é o valor.

Em síntese, a URL completa fornece informações para o back-end sobre o que o usuário está procurando no site do Twitter, bem como informações adicionais sobre a origem da pesquisa e o contexto da pesquisa.
<br>

### Lidando com Query Strings no React Router V6+

No React Router v6, você pode usar query strings em suas rotas com ajuda do módulo `URLSearchParams` e `useSearchParams`. URLSearchParams é uma classe que facilita o trabalho de trabalhar com query strings na URL, permitindo a você extrair as informações da query string de forma simples e eficiente.

Use o hook `useSearchParams` para acessar as informações da query string na sua aplicação. Este hook retorna um objeto com as informações da query string, onde você pode obter os valores usando a sintaxe de objeto, como `searchParams.get('key1')`. Além disso, você pode usar o método `set()` do objeto `searchParams` para definir ou atualizar os valores na query string.

Aqui está um exemplo de como você pode usar query strings com o hook `useSearchParams`:

```javascript
import React, { useState } from 'react';
import { useLocation, useSearchParams, useNavigate } from 'react-router-dom';

function SearchPage() {
  // Pega a localização atual da URL
  const location = useLocation();

  // Pega os parâmetros da query string
  const searchParams = useSearchParams();

  // Busca o valor do parâmetro "q" na query string ou inicializa com uma string vazia
  const searchQuery = searchParams.get('q') || '';

  // Gerencia o estado do valor do input de busca
  const [searchInput, setSearchInput] = useState(searchQuery);

  // Pega a função navigate para navegar para outra página
  const navigate = useNavigate();

  // Manipula o envio do formulário de busca
  const handleSubmit = (event) => {
    // Previne o comportamento padrão de submit do formulário
    event.preventDefault();

    // Define o valor do parâmetro "q" na query string
    searchParams.set('q', searchInput);

    // Navega para a página atual, adicionando os parâmetros da query string
    navigate(`${location.pathname}?${searchParams.toString()}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={searchInput}
        onChange={(event) => setSearchInput(event.target.value)}
      />
      <button type="submit">Buscar</button>
    </form>
  );
}

```
Este código cria uma página de busca que permite ao usuário digitar uma consulta e enviá-la. Aqui estão as coisas importantes que estão acontecendo:

- Usamos `useLocation` e `useSearchParams` do pacote `react-router-dom` para obter informações sobre a localização atual da página (incluindo a query string) e trabalhar com os parâmetros da query string.

- Usamos `useState` para gerenciar o estado do valor do input de busca. Isso permite que o usuário digite algo na caixa de busca e que esse valor seja armazenado para que possamos usá-lo quando o usuário clicar em "Buscar".

- Usamos `useNavigate` para obter a função `navigate` que nos permite navegar para outra página.

- Temos uma função `handleSubmit` que é chamada quando o usuário envia o formulário de busca. Essa função define o valor do parâmetro "q" na query string usando `searchParams.set` e, em seguida, usa `navigate` para navegar para a página atual, adicionando os parâmetros da query string.

- Finalmente, retornamos um formulário que tem um input para digitar a consulta e um botão "Buscar" que, quando clicado, chama a função `handleSubmit`. O estado atual do input de busca é atualizado a cada vez que o usuário digita algo na caixa, graças ao `onChange` no input.

Este código modifica a query string da URL atual quando o formulário é enviado. A query string é a parte da URL após o símbolo de `?` e é composta por pares de chave e valor (por exemplo, `chave=valor`).

Quando o formulário é enviado, o evento `submit` é manipulado pela função `handleSubmit`. Nesta função, o valor do input de busca é definido como o valor do parâmetro `q` na query string usando o método `set` do objeto `searchParams`. Em seguida, a função navigate é usada para navegar para a página atual, adicionando a query string modificada à URL.

Por exemplo, se a URL atual for `www.example.com/search`, após o envio do formulário com o valor de busca `react`, a URL será alterada para `www.example.com/search?q=react`. A query string `?q=react` representa a chave `q` com o valor `react`.

Existem diversas formas de manipular query strings com a biblioteca React Router. Para saber mais, acesse a documentação oficial em [https://reactrouter.com/en/main](https://reactrouter.com/en/main).

---

# Considerações Finais

Parabéns por chegar até aqui! Você agora tem uma compreensão sólida do React Router e como ele pode ser usado para gerenciar rotas em seu aplicativo React. Desde a instalação até os conceitos avançados, você aprendeu como usar os componentes e hooks básicos do React Router, trabalhar com parâmetros de rotas, proteger suas rotas e lidar com query strings.

Com este conhecimento, você pode construir aplicativos React mais avançados e ricos em funcionalidades. Continue aprendendo e experimentando com o React Router para se tornar um profissional ainda mais capacitado.

Em conclusão, o React Router é uma ferramenta poderosa para gerenciar as rotas em seu aplicativo React. Seguindo este guia, você agora tem a base necessária para criar aplicativos com uma navegação clara e fácil de usar.