paint-brush
Técnicas avançadas do React Router V6: indo além do básicopor@sojinsamuel
6,354 leituras
6,354 leituras

Técnicas avançadas do React Router V6: indo além do básico

por Sojin Samuel11m2023/07/02
Read on Terminal Reader

Muito longo; Para ler

O React Router é uma ferramenta incrível que nos permite criar uma navegação dinâmica e suave em nossos aplicativos React. Existem algumas técnicas menos conhecidas que podem elevar suas habilidades de roteamento a um nível totalmente novo. Abordaremos: Lidando com a notória página 404. Criando um indicador de página ativa para destacar a rota atual. Utilizando ganchos `useNavigate` e `useLocation`.
featured image - Técnicas avançadas do React Router V6: indo além do básico
Sojin Samuel HackerNoon profile picture
0-item
1-item

Estou muito animado para compartilhar algumas técnicas avançadas do React Router com você hoje. O React Router é uma ferramenta incrível que nos permite criar uma navegação dinâmica e suave em nossos aplicativos React .


Embora seja comumente usado para necessidades básicas de roteamento, existem algumas técnicas menos conhecidas que podem elevar suas habilidades de roteamento a um nível totalmente novo.


Hoje, compartilharei alguns dos meus favoritos que descobri ao longo do tempo.


Abordaremos:

  1. Lidando com a notória página 404.
  2. Criando um indicador de página ativa para destacar a rota atual.
  3. Utilizando ganchos useNavigate e useLocation .


Ao terminar de ler este artigo, você terá uma forte compreensão dessas técnicas avançadas do React Router e se sentirá confiante em aplicá-las em seus próprios projetos.


Então, vamos mergulhar de cabeça e aprimorar nossas habilidades de roteamento juntos!


Você está pronto? Vamos começar!

Lidando com uma página 404


Ao trabalhar em projetos maiores, é essencial cuidar de rotas que não podem ser encontradas. Muitas vezes nos referimos a essas rotas como rotas 404 porque elas retornam o código de status HTTP 404 quando um documento não é encontrado no servidor.


A propósito, se você é um amante de gatos, pode gostar de conferir http.cat .


Agora, vamos mergulhar na criação de uma rota especial que será acionada sempre que nenhuma das outras rotas corresponder à URL atual no navegador.

 import {BrowserRouter, Routes, Route} from "react-router-dom"; function App() { return <BrowserRouter> <Routes> <Route path="/" element={<p>Landing page</p>}></Route> <Route path="/products" element={<p>Products page</p>}></Route> <Route path="*" element={<p>404 page</p>}></Route> </Routes> </BrowserRouter> }

Ao acessar a página principal / , o usuário será direcionado para a Landing page. Navegar até a página /products os levará à página Produtos. No entanto, se algum outro link for acessado que não corresponda a uma rota específica, a página 404 será exibida.


A razão por trás desse comportamento é a implementação de um <Route> especializado para a página 404, onde a propriedade path é definida como * . Essa configuração garante que o React Router utilizará exclusivamente essa rota quando nenhuma outra rota puder ser correspondida. A colocação específica da Rota 404 é irrelevante e pode ser posicionada em qualquer lugar dentro da seção <Routes>...</Routes> , como um componente integral dela.

página ativa

Outra maneira de os aplicativos usarem as rotas de maneira prática é destacando a página ativa no menu.


Vamos imaginar que você tenha um menu de navegação com dois links:


  1. Home - Este link leva o usuário à página principal / .

  2. Sobre - Este link leva o usuário à página sobre /about .


Com o React Router, torna-se possível destacar automaticamente o link About quando o usuário estiver na rota /about . Da mesma forma, você pode destacar o link Home quando o usuário estiver na rota / . A melhor parte é que você pode conseguir isso sem a necessidade de condicionais complexos.


Aqui está uma maneira simples de fazê-lo funcionar:

 import {NavLink} from "react-router-dom"; function getClassName({isActive}) { if (isActive) { return "active"; // CSS class } } function App() { return <ul> <li> <NavLink to="/" className={getClassName}>Home</NavLink> </li> <li> <NavLink to="/about" className={getClassName}>About</NavLink> </li> </ul> }


O código que você vê acima precisa de algum CSS para fazer a classe active funcionar. Portanto, podemos aprimorá-lo fazendo com que o link do menu da página atualmente ativa apareça em negrito e se destaque.

 .active { font-weight: bold; }


O atributo className do elemento NavLink tem a flexibilidade de aceitar uma função em vez de apenas uma string. Quando você decidir usar uma função, ela receberá um objeto como parâmetro, e esse objeto já terá a propriedade isActive definida nele. Para acessar facilmente essa propriedade dentro da função, usamos a desestruturação incluindo {isActive} no parâmetro.


Em seguida, verificamos se isActive possui um valor verdadeiro. Se for esse o caso, retornaremos o nome da classe CSS active .


Quando o caminho atual no React Router corresponder ao atributo to do componente NavLink , a função isActive será avaliada como um valor booleano.


Como resultado, o React Router incluirá perfeitamente a classe active no elemento <NavLink /> correspondente, indicando-a como a rota atualmente ativa.

versão mais curta

Se preferir uma abordagem mais curta, você pode usar o operador ternário para refatorar o código mencionado acima. Este operador fornece uma maneira de substituir uma instrução if/else usando o formato: condition ? truthy expression : falsy expression .

Eu realmente não uso muito o operador ternário porque muitas vezes pode tornar o código menos legível. No entanto, é aceitável usar neste caso.


Considere o seguinte como exemplo:

 function getClassName({isActive}) { if (isActive) { return "active"; } else { return ""; } }


Você pode substituir o código acima pela seguinte abordagem:

 function getClassName({isActive}) { return isActive ? "active" : ""; }


Você simplesmente precisa garantir que a instrução return seja colocada fora do operador ternário. Quando a condição isActive for verdadeira, a expressão após ? será executado "active" . Caso contrário, a expressão após : será executada "" .


Agora, podemos eliminar a necessidade de uma definição de função separada chamada getClassName . Em vez disso, podemos usar uma função de seta como esta: ({isActive}) => isActive ? "active" : "" .


Se você achar essa alteração muito difícil de ler, poderá continuar usando uma função separada como antes.

O código final ficaria assim:

 import {NavLink} from "react-router-dom"; function App() { return <ul> <li> <NavLink to="/" className={({isActive}) => isActive ? "active" : ""}>Home</NavLink> </li> <li> <NavLink to="/about" className={({isActive}) => isActive ? "active" : ""}>About</NavLink> </li> </ul> }

Oh garoto, eu posso praticamente ouvir seus pensamentos!

Sojin, você quebrou o princípio DRY, não foi?

Este é apenas um exemplo. Não há necessidade de ficar todo excitado 😀

Escolhendo entre Link e NavLink: o que os diferencia?

Você já deve ter notado que estou usando NavLink em vez do nosso amigo de sempre, Link . Mas não se preocupe, deixe-me explicar o porquê. Veja bem, o componente <Link /> não permite que você use uma definição de função para a propriedade className . Sim, pode ser surpreendente, mas é assim que funciona quando você está trabalhando com <Link /> .


Um erro comum que vi são os desenvolvedores juniores do React tentando usar definições de função na prop className de um componente <Link /> , que simplesmente não funciona.


Se você estiver interessado, posso escrever um artigo sobre esse tópico. Apenas deixe-me saber nos comentários!

useNavigate

Em certas circunstâncias, pode ser necessário realocar páginas programaticamente em seu aplicativo React. Por exemplo, para redirecionar o visitante para uma página específica, você pode enviar uma solicitação e aguardar a resposta.


Aqui estão alguns exemplos:

  • Se o usuário não estiver conectado, envie-o para a página de login.
  • Depois que a solicitação getLogin for concluída com êxito, redirecione o usuário para /dashboard .


Isso requer o uso do gancho useNavigate() , que retorna uma função que pode ser usada para redirecionar programaticamente o usuário para uma nova rota.


Dê uma olhada:

 import React, {useEffect} from "react"; import {useNavigate} from "react-router-dom"; function HelpPage() { const navigate = useNavigate(); useEffect(() => { const isLoggedIn = window.localStorage.getItem("isLoggedIn"); if (!isLoggedIn) { navigate("/login"); } }, []); return <h2>Help page</h2>; }

Usar o BrowserRouter é essencial!

Neste exemplo, estamos verificando se localStorage tem um valor atribuído à chave isLoggedIn . Caso contrário, redirecionaremos o usuário para a página /login usando a função navigate("/login") .


Para fazê-lo funcionar, lembre-se de usar o gancho useNavigate() dentro de um componente aninhado dentro do componente <BrowserRouter /> . Caso contrário, não funcionará corretamente.


Por exemplo, o exemplo a seguir não funcionará:

 import React from "react"; import {BrowserRouter, useNavigate} from "react-router-dom"; function App() { // ❌ This breaks because the component was not wrapped by BrowserRouter, but its children are. const history = useNavigate(); return <BrowserRouter> {/* ... */} </BrowserRouter>; }

Se você estiver tentando usar o gancho useNavigate() dentro do componente App() , poderá ter um pequeno contratempo. Isso porque não funcionará a menos que você envolva o componente App() com <BrowserRouter /> .


Mas não se preocupe!


A boa notícia é que todos os componentes filhos dentro de App serão automaticamente encapsulados por <BrowserRouter /> , então você pode usar useNavigate() com prazer nesses componentes filhos sem nenhum problema.


No entanto, se você realmente precisa usar useNavigate() no próprio componente <App /> , há uma solução simples. Você só precisa criar um componente pai que envolva <App /> e certifique-se de mover o <BrowserRouter /> dentro desse componente pai. Depois de fazer isso, você estará pronto e poderá usar useNavigate() no componente <App /> para o conteúdo do seu coração 💗

Garantindo a acessibilidade e o uso adequado do link

Quando se trata de tornar seu site acessível, é importante prestar atenção em como seus links estão estruturados. Para garantir isso, é recomendável usar elementos <Link /> em vez de outros métodos.


Por que?


Bem, esses elementos serão renderizados automaticamente como tags <a> , que são conhecidas por seus recursos de acessibilidade .

Agora, aqui vai uma dica amigável: evite substituir seus elementos <Link /> normais pelo método .push() fornecido por useNavigate() . Este método só deve ser utilizado nos casos em que o uso de um elemento <Link /> não é possível.


Quando isso acontece?

Normalmente, é quando você precisa redirecionar os usuários programaticamente com base em determinada lógica, como o resultado de uma operação fetch() .

useLocation

E se você quiser executar um trecho de código toda vez que o React Router o levar a um novo endereço?

Você pode fazer isso facilmente com a ajuda do gancho useLocation . Mas antes de mergulharmos nos detalhes, vamos explorar alguns cenários em que isso pode ser útil. Um dos casos de uso mais comuns é enviar um evento de exibição de página para seu serviço de análise, como o Google Analytics.


No entanto, vale a pena mencionar que o Google Analytics 4 agora cuida disso automaticamente, então você não precisa necessariamente implementá-lo sozinho.


No entanto, aprender sobre o gancho useLocation ainda é valioso, pois você pode encontrar outros propósitos para ele. Por exemplo, você pode usá-lo para integração com outras bibliotecas e serviços analíticos ou para executar ações específicas com base nas rotas visitadas.


As possibilidades são infinitas!

gancho de localização de uso

O gancho useLocation é super útil porque fornece informações sobre a rota que está sendo usada no momento.


Aqui está um guia amigável sobre como usar o gancho useLocation:

 import {BrowserRouter, Routes, Route, useLocation} from "react-router-dom"; import {createRoot} from "react-dom/client"; function App() { const location = useLocation(); console.log(location.pathname); return <Routes> {/* routes here... */} </Routes> } createRoot(document.querySelector("#react-root")).render(<BrowserRouter><App /></BrowserRouter>);


Agora, você pode acessar as informações da rota por meio da variável de localização. É um objeto que contém o pathname atual.


Para descobrir qual rota o usuário está navegando no momento, basta usar location.pathname . Ele fornecerá algo como / , /about ou qualquer outra rota que você configurou.


Lembre-se, assim como com o gancho useNavigate , é importante ter seu código rodando dentro de um componente que é agrupado por <BrowserRouter /> . Caso contrário, o gancho useLocation não fará sua mágica.

Respondendo a mudanças de localização

Quando o local muda, você pode usar o gancho useLocation para acessar o caminho da URL atual no React Router. Ao agrupar seu código com um gancho useEffect e definir a dependência como location , você pode executar uma parte específica do código sempre que houver uma navegação para uma nova URL.


Aqui está um exemplo de como fazer:

 import React, {useEffect} from "react"; import {BrowserRouter, Routes, Route, useLocation} from "react-router-dom"; import {createRoot} from "react-dom/client"; function App() { const location = useLocation(); // run a piece of code on location change useEffect(() => { console.log(location.pathname); // send it to analytic, or do some conditional logic here }, [location]); return <Routes> {/* routes here... */} </Routes> } createRoot(document.querySelector("#react-root")).render(<BrowserRouter><App /></BrowserRouter>);

Sempre que o usuário move para uma nova rota durante a navegação, o código dentro do gancho useEffect será executado e fará seu trabalho. É basicamente uma maneira de garantir que um código específico seja executado sempre que houver uma alteração no objeto de localização.

Bom trabalho, agora você é um especialista em roteador React 🥳

Para finalizar, este artigo forneceu uma compreensão mais profunda do React Router. Embora você possa não usar todos os recursos discutidos aqui. Ainda assim, é fantástico que você esteja ciente deles. Se você precisar incorporar uma funcionalidade semelhante no futuro, você sabe exatamente onde procurar. Portanto, certifique-se de salvar ou marcar esta postagem para facilitar a referência. E lembre-se, se você tiver alguma dúvida ou precisar de mais ajuda, sinta-se à vontade para entrar em contato comigo no Twitter. Estou aqui para ajudar!