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.
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!
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.
Outra maneira de os aplicativos usarem as rotas de maneira prática é destacando a página ativa no menu.
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.
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.
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.
function getClassName({isActive}) { if (isActive) { return "active"; } else { return ""; } }
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.
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 😀
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!
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.
/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>; }
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 💗
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.
Normalmente, é quando você precisa redirecionar os usuários programaticamente com base em determinada lógica, como o resultado de uma operação fetch()
.
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!
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.
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.
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.
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!