Em um site da web, onde temos muitas telas e precisamos acessá-las de maneira dinâmica e rápida, utilizar rotas para a navegação do usuário é a melhor solução. Existem muitas ferramentas que resolvem esse tipo de problema, mas para as pessoas desenvolvedoras de React, o React Router Dom é o mais aconselhável.
Ao criarmos várias telas com apenas HTML e Javascript puro, nos deparamos com alguns tipos de problemas, como a não escalabilidade e o alto retrabalho que acabamos tendo ao decorrer do desenvolvimento.
Por isso, utilizar frameworks é um processo obrigatório no desenvolvimento web moderno. Isso se deve ao fato destas ferramentas serem muito fáceis e flexíveis de se usar. Então, que tal continuar conosco para entender a dinâmica de roteamento do React? Neste artigo você vai conferir:
- O que é o React router dom e para que serve?
- O que são e para que servem as rotas no React?
- Quais são os componentes usados no React router dom?
- Conheça os 4 Hooks do React router!
- O que é e como funcionam as nested routes?
- Como instalar e configurar o React router dom?
O que é o React router dom e para que serve?
O React Router Dom é uma biblioteca para o React criada com o objetivo de resolver problemas de rotas para as páginas de um site e tornar o desenvolvimento muito mais simples e escalável. Com ela, podemos declarar caminhos do nosso site para renderizar componentes e até mesmo resolver parâmetros na URL.
O que são e para que servem as rotas no React?
Ao criarmos um site no React é necessário ter uma estrutura de rotas. Quando a pessoa usuária começa a navegar pelo site, precisa existir uma lógica para exibir os componentes de acordo com as chaves na URL.
Além disso, as rotas não são um recurso específico do React — elas estão presentes por toda a internet. Isto é, quando acessamos um site qualquer e começamos a navegar por ele, estamos utilizando o sistema de rotas. Podemos analisar um exemplo no próprio site do blog da Trybe:
Na primeira imagem, temos um print da página inicial do site e de como a barra de URL se comporta. Agora, veja o que acontece quando vamos para outra página do site:
Nesta segunda imagem, quando navegamos para esta outra URL, o próprio site mostra a tela referente ao identificador que está no campo de texto com sua lógica de rotas. Como é possível observar, desenvolvimento-web é a chave dessa tela.
Quais são os componentes usados no React router dom?
O React Router Dom tem os seus componentes divididos em três categorias, sendo que cada categoria é fundamental para o funcionamento da aplicação.
Roteador
O Roteador é o principal componente para que um projeto consiga executar o roteamento das páginas. Para isso, contamos com dois componentes, BrowserRouter e HashRouter, os dois tendo suas próprias características.
O HashRouter cria um tipo de roteamento no qual a URL do seu site fica com o símbolo de # (hashtag) antes de cada chave. Assim, a URL www.site.com.br/#/tela seria um exemplo disso. Inclusive, esse componente não é muito utilizado justamente por esse motivo.
No BrowserRouter, as URLs estão no padrão convencional. Um exemplo é a URL www.site.com.br/tela. Em alguns cenários, este componente vem instalado por padrão no React.
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { BrowserRouter } from "react-router-dom";
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root')
);
Podemos ver neste exemplo que importamos o BrowserRouter e declaramos ao redor do componente de App.
Gerenciador de rotas
Essa etapa é um pouco diferente dependendo de qual versão do React Router Dom você está usando. No nosso caso, vamos utilizar a versão 6.x da biblioteca.
Os componentes são simplificados em Routes e Route, sendo que um é o gerenciador do outro. Visualizamos a sintaxe destes componentes em uma possível aplicação real:
// App.js
import './App.css';
import {
Routes,
Route
} from "react-router-dom";
import Home from './Home';
import About from './About';
import NotFound from './NotFound';
function App() {
return (
<div className="App">
<Routes>
{/* Componente da tela inicial */}
<Route index element={<Home />} />
{/* Componente de uma rota específica */}
<Route path="about" element={<About />} />
{/* Componente para quando não encontrar uma rota */}
<Route path="*" element={<NotFound />} />
</Routes>
</div>
);
}
export default App;
Também podemos visualizar as telas no nosso navegador:
Navegação
Para a navegação, contamos com dois tipos de componentes, o Link e o NavLink. O primeiro é a forma de navegar pelas páginas do React:
// App.js
import './App.css';
import {
NavLink
} from "react-router-dom";
function App() {
return (
<div className="App">
<div>
// Link para a página inicial
// Quando estiver ativo, vai ficar vermelho
<NavLink to="/" style={({ isActive }) =>
isActive ? { color: 'red' } : undefined
}
>
Navegar para a tela inicial
</NavLink>
<br/>
// Link para a tela de about
// Quando estiver ativo, vai ficar vermelho
<NavLink to="/about" style={({ isActive }) =>
isActive ? { color: 'red' } : undefined
}
>
Navegar para a tela de about
</NavLink>
</div>
// ...
</div>
);
}
export default App;
Já no segundo, temos alguns estilos e configurações a mais sobre o Link:
// About.js
import { Link } from "react-router-dom";
function About() {
return (
<div className="About">
Sobre
<br />
<Link to="/">
Voltar para a Home
</Link>
</div>
);
}
export default About;
Com isso, nossa tela inicial ficou dessa forma:
E a tela de about ficou assim:
Temos que lembrar que, por baixo dos panos, estes componentes são apenas elementos de ancoragem (<a>) e podem ser customizados por CSS.
Conheça os 4 principais Hooks do React router!
Com as últimas versões do React Router, temos alguns hooks que podem nos auxiliar ao desenvolver nossas aplicações.
Hook useNavigate
O hook useNavigate que é a versão melhorada do useHistory, permite que a pessoa desenvolvedora tenha acesso à interface atual do History. Com ela, conseguimos trocar de página programaticamente e sem a necessidade de nenhum componente.
// About.js
import { useNavigate } from "react-router-dom";
function About() {
const navigate = useNavigate()
const goHome = () => {
navigate("/")
}
return (
<div className="About">
Sobre
<br />
<button onClick={goHome}>
Voltar para a tela inicial
</button>
</div>
);
}
export default About;
O resultado ficou assim:
Quando a pessoa usuária clicar no botão, será redirecionada para a tela inicial.
Hook useLocation
Este outro hook serve para exibir as informações de navegação da pessoa usuária atual. Pode ser útil para realizar alguma tarefa a partir da mudança deste estado.
// App.js
import {
useLocation
} from "react-router-dom";
import { useEffect } from 'react';
function App() {
const location = useLocation()
useEffect(() => {
console.log("Navegação alterada: ", location)
}, [location])
return (
<div className="App" />
);
}
export default App;
A função callback do useEffect é chamada a cada tela que a pessoa usuária visita.
Hook useParams
O comportamento deste hook é ideal para páginas com parâmetros dinâmicos. Ou seja, na URL www.site.com.br/usuario/123, o número 123 é um parâmetro que definimos no roteamento e conseguimos recuperar com o useParams.
// App.js
import {
Routes,
Route
} from "react-router-dom";
import User from './User';
function App() {
return (
<div className="App">
<Routes>
// O :id representa o nome do parâmetro que a gente espera receber
<Route path="user/:id" element={<User />} />
</Routes>
</div>
);
}
export default App;
E:
// User.js
import { useParams } from "react-router-dom";
function User() {
const { id } = useParams()
return (
<div className="user">
O id é {id}
</div>
);
}
export default User;
Quando entramos na rota de user com valor no caminho, recuperamos o valor do parâmetro e exibimos na tela.
Hook useMatch
Este último hook, conhecido como useRouteMatch nas versões anteriores a 6.x, tem um objetivo bem simples: verificar se a página atual corresponde com alguma rota que a pessoa desenvolvedora passou como parâmetro.
// App.js
import {
useMatch
} from "react-router-dom";
function App() {
// Verificamos se a rota atual é equivalente a página inicial
const isRouteHome = useMatch("/")
return (
<div className="App">
<p>
É a página inicial?
<br />
<span>
{isRouteHome ? "Sim" : "Não"}
</span>
</p>
</div>
);
}
export default App;
Neste exemplo, demos a instrução para que o hook verifique se a rota atual é a da página inicial:
Desta maneira, conseguimos criar as nossas próprias lógicas de verificação das rotas.
Hooks extras
Nas novas atualizações do React Router temos alguns hooks que não são considerados principais e que são recomendados para casos de uso excepcionais. Alguns destes hooks são:
- useResolvedPath
- useRoutes
- useSearchParams
- useInRouterContext
- useLinkClickHandler
- useLinkPressHandler
- useNavigationType
Para entender o que cada um deles faz, é aconselhável olhar as documentações oficiais da biblioteca.
O que é e como funcionam as nested routes?
Nested routes, ou rotas aninhadas, são telas que renderizam um componente pai e diversos componentes filhos a partir do caminho que está digitado na barra de busca, com base nesse valor. Seguindo a lógica das nested routes, se temos uma tela de usuário, podemos criar a tela de detalhes e de perfil.
Como funciona na prática?
Na prática, é muito simples implementar essa lógica no React Router utilizando o novo componente Outlet, que gerencia as lógicas de mostrar os componentes a partir da URL. Vamos ver alguns exemplos, a seguir:
// App.js
import {
Routes,
Route
} from "react-router-dom";
import Home from './Home';
import User from './User';
import UserDetails from './UserDetails';
import UserProfile from './UserProfile';
function App() {
return (
<div className="App">
<Routes>
<Route index element={<Home />} />
// Criamos a rota de usuário
<Route path='user' element={<User />}>
// Criamos a rota de detalhes do usuário
<Route path="details" element={<UserDetails />} />
// Criamos a rota de perdil do usuário
<Route path="profile" element={<UserProfile />} />
</Route>
</Routes>
</div>
);
}
export default App;
// UserProfile.js
function UserProfile() {
return (
<div className="userProfile">
<p>
Perfil do usuário
</p>
</div>
);
}
export default UserProfile;
// UserProfile.js
function UserProfile() {
return (
<div className="userProfile">
<p>
Perfil do usuário
</p>
</div>
);
}
export default UserProfile;
// User.js
import { Link, Outlet, useLocation } from "react-router-dom";
function User() {
return (
<div className="user">
<h3>
Usuário
</h3>
<div className="container-user-links">
<Link to="/user/profile">
Ver perfil
</Link>
<Link to="/user/details">
Ver detalhes
</Link>
</div>
// Componente do React Router que renderiza os componentes filhos
<Outlet />
</div>
);
}
export default User;
Na imagem a seguir, estamos na rota /profile, na qual o componente de perfil do usuário é renderizado:
Agora, temos o renderizamento da página de detalhes:
A construção é simples e flexível. Como você viu, criamos uma forma de exibir informações dentro de um componente a partir da URL do site com poucas linhas de código.
Como instalar e configurar o React router dom?
Vamos te mostrar como o React Router Dom é fácil de instalar e muito poderoso na hora de gerenciar as telas.
Criando um projeto react e acessando a pasta
Rode o seguinte comando no seu terminal de preferência:
npx create-react-app react-router-dom-trybe
Com o projeto devidamente criado, basta entrar na pasta dele e abri-lo na sua IDE preferida. No nosso caso, usaremos o VSCode.
cd react-router-dom-trybe
Instalando o React router dom
Antes de mais nada, precisamos instalar a dependência do React Router Dom em nosso projeto. Utilize o NPM ou Yarn para isso.
npm install react-router-dom
Certifique-se que não ocorreu nenhum erro e que a versão está correta.
Criando o arquivo route.js
Na pasta principal src, crie o arquivo route.js conforme o exemplo:
Agora, vamos adicionar a casca para o nosso roteador.
//Routes.js
import { Routes as RoutesDom } from "react-router-dom"
const Routes = () => {
return (
<RoutesDom>
</RoutesDom>
)
}
export default Routes
Observação: a única mudança que tivemos de fazer aqui foi a de adicionar um alias para o componente Routes do React Router, já que ele é incompatível com o nome do nosso próprio componente, o Routes.
Importando o route.js para o react app
No App.js basta que a gente importe o nosso componente e o adicione no código JSX.
//App.js
import './App.css';
import Routes from './routes';
function App() {
return (
<div className="App">
<Routes />
</div>
);
}
export default App;
Já no arquivo index.js, precisamos adicionar o componente fundamental para o funcionamento das rotas, o BrowserRouter.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
Criando os componentes: home, about e user!
Para os nossos testes, criaremos três componentes para as telas.
// Home.js
const Home = () => {
return (
<div>
Tela inicial
</div>
)
}
export default Home
// About.js
const About = () => {
return (
<div>
Tela de sobre
</div>
)
}
export default About
// User.js
const User = () => {
return (
<div>
Tela do usuário
</div>
)
}
export default User
Agora, no arquivo de rotas, instanciamos cada componente com seu devido caminho.
// Routes.js
import { Route, Routes as RoutesDom } from "react-router-dom"
import Home from "./Home"
import About from "./About"
import User from "./User"
const Routes = () => {
return (
<RoutesDom>
<Route index element={<Home />} />
<Route path="about" element={<About />} />
<Route path="user" element={<User />} />
</RoutesDom>
)
}
export default Routes
Para melhorar nossa navegação entre as telas, adicionamos alguns NavLinks no arquivo App.js.
// App.js
import './App.css';
import { NavLink } from 'react-router-dom';
import Routes from './routes';
function App() {
return (
<div className="App">
<div>
<NavLink to="/">
Home
</NavLink>
<NavLink to="/about">
About
</NavLink>
<NavLink to="/user">
User
</NavLink>
</div>
<Routes />
</div>
);
}
export default App;
Execute o app react
Para executar o projeto é bem simples. Com o diretório aberto no terminal, rode o comando a seguir e espere carregar a tela.
npm start
Assim, temos o seguinte resultado:
A partir desse ponto de entrada, você pode expandir os seus conhecimentos e ir aumentando tanto os componentes quanto a quantidade de rotas e lógicas!
Conclusão
Quando criamos sites grandes, precisamos de várias telas para entregar às pessoas usuárias todas as funcionalidades e informações de que elas precisam. Por isso, as formas tradicionais de se realizar o redirecionamento de telas não são mais tão eficazes. Sabendo disso, o React Router Dom se tornou a principal ferramenta para facilitar o trabalho de manejar rotas através do React.
Com a ajuda de componentes e hooks com lógicas totalmente personalizáveis, a pessoa desenvolvedora tem menos trabalho ao criar novas telas e pode se preocupar mais com o desenvolvimento delas.
E por falar nisso, que tal aprender mais sobre o mundo do Frontend: o que é e como ser um programador frontend?