Navegação no React: não é apenas um clique em um link
\n\nVocê já se perguntou como fazer o React Router navegar para outra página não por um clique do usuário, mas por um comando do código? Por exemplo, após o envio bem-sucedido de um formulário, autenticação ou simplesmente após 5 segundos? Se sim, você veio ao lugar certo. A pergunta "How can I programmatically navigate using React Router?" é uma das mais populares no Stack Overflow, e não é à toa. Parece simples, mas na realidade existem muitas armadilhas escondidas aqui, especialmente quando se trata de desempenho.
\n\nNeste artigo, não vamos apenas mostrar como usar useNavigate. Vamos analisar como fazer isso corretamente, rapidamente e sem travamentos. Você aprenderá quais padrões levam a vazamentos de memória e quais levam a uma navegação extremamente rápida. Vamos lá!
Clássico: useNavigate — sua principal ferramenta
\n\nA partir do React Router v6, useNavigate substituiu o antigo useHistory. Este é um hook que retorna a função navigate. Fica assim:
import { useNavigate } from 'react-router-dom';\n\nfunction LoginButton() {\n const navigate = useNavigate();\n\n const handleLogin = () => {\n // Lógica de autenticação aqui\n const user = { name: 'Ivan' };\n // Após o sucesso — redirecionamento\n navigate('/dashboard', { replace: true });\n };\n\n return <button onClick={handleLogin}>Entrar</button>;\n}\n\n\nObserve o parâmetro { replace: true }. Ele substitui a entrada atual no histórico, em vez de adicionar uma nova. Isso é crítico para o login, para que o usuário não volte para a página de login.
Para onde você pode navegar?
\n- \n
- Caminho absoluto:
navigate('/about')\n - Caminho relativo:
navigate('../settings')\n - Voltar/avançar no histórico:
navigate(-1)ounavigate(2)\n
Nível avançado: navegação fora dos componentes
\n\nE se você precisar fazer um redirecionamento de uma função comum, que não está dentro de um componente React? Por exemplo, de um action creator no Redux ou de um interceptor axios? O hook useNavigate não funcionará aqui — hooks só são chamados dentro de componentes funcionais.
Solução: criar um componente wrapper personalizado ou usar um objeto de roteador global. No React Router v6, existem os componentes especiais RouterProvider e createBrowserRouter para isso, mas também há uma maneira mais simples — salvar a referência a navigate em uma variável.
// router.js\nimport { createBrowserRouter, RouterProvider } from 'react-router-dom';\n\nexport const router = createBrowserRouter([...]);\n\n// navigation.js — módulo separado para navegação\nlet navigateFunction = null;\n\nexport const setNavigate = (navigate) => {\n navigateFunction = navigate;\n};\n\nexport const navigateTo = (path) => {\n if (navigateFunction) {\n navigateFunction(path);\n } else {\n console.warn('Navegação ainda não está pronta');\n }\n};\n\n// App.js\nimport { useNavigate } from 'react-router-dom';\nimport { setNavigate } from './navigation';\nimport { useEffect } from 'react';\n\nfunction App() {\n const navigate = useNavigate();\n\n useEffect(() => {\n setNavigate(navigate);\n }, [navigate]);\n\n return /* seu código */;\n}\n\n\nAgora, de qualquer função (seja de um setTimeout, seja de um fetch), você pode chamar navigateTo('/home'). Conveniente? Sim. Seguro? Apenas se você não esquecer de limpar a referência ao desmontar o componente.
Otimização de desempenho: por que sua aplicação está lenta?
\n\nNavegação programática não é apenas uma chamada de função. É um gatilho para uma re-renderização completa da página. E se você fizer isso