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:
- Lidando com a notória página 404.
- Criando um indicador de página ativa para destacar a rota atual.
- Utilizando ganchos
useNavigate
euseLocation
.
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:
Home - Este link leva o usuário à página principal
/
.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!