React router dom: criando e manipulando rotas com react!

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?

Logo do react router

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:

Captura de uma tela do site da Trybe, onde podemos ver a URL https://blog.betrybe.com

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:

Captura de uma tela do site da Trybe, onde podemos ver a URL https://blog.betrybe.com/desenvolvimento-web/

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:

Exemplo de tela inicial após aplicação do código, onde é possível ver a URL localhost:3000 e os dizeres "Tela inicial"
Exemplo de tela de about após aplicação do código, onde é possível ver a URL localhost:3000/about e os dizeres "Sobre"
Exemplo de tela de erro após aplicação do código, onde é possível ver a URL localhost:3000/error e os dizeres "404 não encontrou"

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:

Mesmo exemplo de tela inicial após aplicação do código, onde agora é possível ver a URL localhost:3000 e os dizeres "Navegar para a tela inicial", "Navegar para a tela de about" e "Tela Inicial"

E a tela de about ficou assim:

Mesmo exemplo de tela de about após aplicação do código, onde agora é possível ver a URL localhost:3000/about e os dizeres "Navegar para a tela inicial", "Navegar para a tela de about", "Sobre" e "Voltar para a Home"

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:

Mesmo exemplo de tela de about após aplicação do código, onde agora é possível ver a URL localhost:3000/about, os dizeres "Navegar para a tela inicial", "Navegar para a tela de about", "Sobre", e um botão com os dizeres "Voltar para a Home"

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.

Exemplo de tela de user com valor no caminho, onde é possível ver a URL localhost:3000/user/23 e os dizeres "Navegar para a tela inicial", "Navegar para a tela de about" e "O id é 23"

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:

Tela com a URL localhost:3000, onde é possível ler os dizeres "É a página inicial? Sim".
Tela com a URL localhost:3000/about, onde é possível ler os dizeres "É a página inicial? Não".

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:

Exemplo de página com a URL localhost:3000/user/profile com o componente de perfil de usuário renderizado. Nela, conseguimos ler os dizeres "Perfil do usuário", além dos demais já catalogados nos exemplos anteriores

Agora, temos o renderizamento da página de detalhes:

Exemplo de página com a URL localhost:3000/user/details com o componente de detalhes renderizado. Nela, conseguimos ler os dizeres "Detalhes do usuário", além dos demais já catalogados nos exemplos anteriores

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:

Captura de tela onde é possível ver a pasta principal src e o arquivo route.js

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:

Exemplo de tela de about, otimizada, onde temos botões para a navegação
Exemplo de tela de usuário, otimizada, onde temos botões para a navegação

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?