React Router: Entenda de uma vez por todas

O que é o React Router?

É uma biblioteca utilizada em aplicações SPA em projetos React. Essa biblioteca é usada para o gerenciamento de rotas/roteamento de navegação. Nós permitindo controlar quais componentes serão visualizados em determinada URL e sem precisar recarregar a página inteira, apenas os componentes que foram atualizados.

Caso não saiba o que é SPA basta clicar aqui.

Roteamento

O roteamento basicamente é mostrar diversas páginas e o usuário poder acessá-las, por meio de uma URL ou de um elemento.

Agora vamos criar um projeto React com Javascript.

npx create-vite .

Após inserir o comando acima, basta selecionar a opção ReactJS e posteriormente Javascript.

Por padrão o React ele não possui o roteamento então para podermos utilizar o roteamento no React temos de instalar uma biblioteca em nosso projeto.

npm install react-router-dom

Após instalado o ReactRouter em seu projeto, devemos encapsular o componente App, mas ele pode ter outro nome caso você tenha alterado. Usaremos o componente do React Router para realizar o encapsulamento que é o BrowserRouter. Então através dele já podemos começar a utilizar as rotas pois ele está englobando toda a aplicação. A imagem abaixo é referente ao arquivo main.js.

React Router BrowserRouter

Componentes do React Router

Agora iremos utilizar alguns componentes, são eles:

  • Routes: Ele irá englobar as nossas rotas, dentro dele é definido as páginas da nossa aplicação.
  • Route: É onde se define a página, ele possui dois argumentos, o path que é a url da página e o element que é o componente que será mostrado. Normalmente se cria um componente pai e dentro dele é montando a página e o componente pai é informado no element.
  • Link: É semelhante a tag <a> do HTML, porém quando utilizado ele não recarrega a página, diferente da tag <a>. O componente Link possui um argumento é o to, que é passado a url da página na qual o usuário irá quando for clicada.

Também temos o componente NavLink ele é muito semelhante ao Link porém ele é muito útil ao criar menus na qual necessita de estilo para mostrar a página ativa pois o NavLink já coloca a classe active no item da página atual. Segue exemplo abaixo.

//src/App.jsx
import { NavLink, Route, Routes } from "react-router-dom";
import "./App.css";
import Home from "./components/Home";
import Contact from "./components/Contact";

const Navbar = () => {
  return (
    <nav>
      <ul>
        <li>
          <NavLink to="/">Home</NavLink>
        </li>
        <li>
          <NavLink to="contact">Contato</NavLink>
        </li>
      </ul>
    </nav>
  );
};

function App() {
  return (
    <>
    <Navbar />
      <Routes >
        <Route path="/" element={<Home />} />
        <Route path="/contact" element={<Contact />} />
      </Routes>
    </>
  );
}

export default App;
//src/App.css
nav ul a.active {
  color: rgb(34 197 94);
}
Renderização

Então criaremos um componente para cada página para melhor entendimento. Dentro de src crie uma pasta com nome components e dentro desta pasta crie dois arquivos .jsx, Home e Contact. Esses dois componentes serão nossas páginas.

Dica: Para criar de maneira mais rápida o componente basta digitar no seu arquivo em branco rafce. Assim ele criará o template base.

//src/components/Home.jsx
import React from 'react'

const Home = () => {
  return (
    <div>
      Home
    </div>
  )
}

export default Home;
//src/components/Contact.jsx
import React from 'react'

const Contact = () => {
  return (
    <div>
      Contato
    </div>
  )
}

export default Contact;

Com nossas paginas criadas, vamos no nosso arquivo App.jsx e vamos deixar apenas a estrutura base com o css importado, e adicionaremos as importações dos nossos componentes Home e Contact, e as importações do react-router, Routes, Route e Link.

import { Route, Routes } from 'react-router-dom'
import './App.css'
import Home from './components/Home'
import Contact from './components/Contact'

function App() {
  return (
    <>
      <Routes>
        <Route path='/' element={<Home/>}/>
        <Route path='/contact' element={<Contact/>}/>
      </Routes>
    </>
  )
}

export default App;

useNavigate

O useNaviagate é utilizado quando se torna necessário redirecionar o usuário para determinada página. Dada a seguinte situação: Depois de logado no sistema o usuário veja a página Dashboard. Então quando ele efetuar o login corretamente podemos redirecionar ele para a página de Dashboard.

Dessa forma iremos criar dois componentes, Login e Dashboard, em seguida vamos adiciona-los a nossas rotas. E depois no nosso componente Navbar iremos adicionar o link para irmos a página de Login.

//src/App.jsx
function App() {
  return (
    <>
    <Navbar />
      <Routes >
        <Route path="/" index element={<Home />} />
        <Route path="/contact" element={<Contact />} />
        <Route path="/login" element={<Login />} />
        <Route path="/dashboard" element={<Dashboard />} />
      </Routes>
    </>
  );
}
//src/App.jsx
const Navbar = () => {
  return (
    <nav>
      <ul>
        <li>
          <NavLink to="/">Home</NavLink>
        </li>
        <li>
          <NavLink to="contact">Contato</NavLink>
        </li>
        <li>
          <NavLink to="login">Login</NavLink>
        </li>
      </ul>
    </nav>
  );
};

Dentro do nosso componente Login iremos adicionar o useNavigate e o utilizaremos para efetuar o redirecionamento quando o usuário clicar no botão Login.

//src/components/Login.jsx
import React from 'react';
import { useNavigate } from 'react-router';

const Login = () => {
  const navigate = useNavigate();

  const handleLogin = (e) => {
    e.preventDefault();
    navigate("/dashboard");
  }
  return (
    <form onSubmit={handleLogin}>
      <button type='submit'>Login</button>
    </form>
  )
}

export default Login;

Quando instanciamos o useNavigate temos acesso aos seus métodos, assim podemos utiliza-lo para redirecionar o usuário. Passando a url da página como parâmetro na instancia criada realizamos o redirecionamento. No exemplo acima coloquei o nome da minha instancia de navigate mas pode ser a nomenclatura que achar ideal para seu projeto.

Rotas aninhadas

Agora vamos no seguinte cenário, onde o usuário está na tela de Dashboard e possui um botão de mensagens. Esse componente está dentro do Dashboard e nossa url é para ficar /dashboard/messages. Então vamos criar o nosso componente de mensagens e vamos aninhar a nossa rota com a dashboard. Dentro do componente de Dashboard colocaremos um Link para a url messages.

//src/App.jsx

function App() {
  return (
    <>
    <Navbar />
      <Routes >
        <Route path="/" index element={<Home />} />
        <Route path="/contact" element={<Contact />} />
        <Route path="/login" element={<Login />} />
        <Route path="/dashboard" element={<Dashboard />}>
          <Route path="messages" element={<Messages />}/>
        </Route>
      </Routes>
    </>
  );
}
export default App;
//src/components/Messages.jsx

import React from 'react'

const Messages = () => {
  return (
    <div>
      Mensagens
    </div>
  )
}

export default Messages;
//src/components/Dashboard.jsx

import React from 'react'
import { Link } from 'react-router-dom';

const Dashboard = () => {
  return (
    <div>
      Dashboard 
      <Link to="messages">Mensagens</Link>
    </div>
  )
}

export default Dashboard;

Sendo assim quando entrarmos na tela de Dashboard é para conter um botão para a página mensagens.

Porém ao clicar em Mensagens, nada acontece apenas a url é alterada. Isso se da por conta que precisamos de um componente chamado Outlet que pertence ao react router. Ele deve ser colocado na rota pai do aninhamento que fizemos, em nosso caso será no componente Dashboard.

const Dashboard = () => {
  return (
    <div>
      Dashboard<br/>
      <Link to="messages">Mensagens</Link>
      <Outlet />
    </div>
  )
}

Os elementos da rota pai usam o Outlet para renderizar seus elementos de rota filho.

Rotas dinâmicas

Em algumas situações onde temos que listar alguma coisa, por exemplo vários usuários e ao clicar em um desses usuários ele exiba seus detalhes. Se torna inviável criar um componente para cada usuário. É ai que as rotas dinâmicas entram, pois conseguimos dinamizar a url e utilizar apenas um componente para fazer essa exibição de detalhes.

Vamos criar nossa rota para exibir os detalhes dos usuários porém terá um diferenças na url, ao final dela colocaremos :userId, porém pode ser qualquer outro nome. É importante que fique descritivo para quando você ver já saber do que se trata.

Então dentro do componente Routes colocaremos o código abaixo, essa nomenclatura de :userId informa que essa rota terá valores dinâmicos.

//src/App.jsx
<Route path="/user/:userId" element={<UserDetails />} />

Criaremos nosso componente para exibir os detalhes do usuário, mas nele usaremos o useParams, esse método captura a parte da url que é dinâmica.
Na nossa constante temos que colocar o mesmo nome que foi colocado na url, no nosso caso foi :userId, assim ele irá capturar esse valor.

//src/components/UserDetails.jsx
import React from 'react'
import { useParams } from 'react-router-dom'

const UserDetails = () => {
  const { userId } = useParams()
  return (
    <div>
      Detalhes do usuário {userId}
    </div>
  )
}

export default UserDetails;

Agora vamos criar adicionar nossas rotas ao Link. Adicione esse código abaixo do Routes.

//src/App.jsx
<div>
  <h2>Usuários</h2>
  <Link to="/user/1">Usuário 1</Link>
  <Link to="/user/2">Usuário 2</Link>
  <Link to="/user/3">Usuário 3</Link>
</div>
Ao clicar em um usuário

Essa forma se torna muito útil quando feito uma conexão com um banco de dados, na qual você faz a listagem de usuários, quando clicado no usuário ele faz uma requisição e trás todos os detalhes do usuário em questão.

Criando página 404

Ter uma página informando que o conteúdo na qual ele tenta acessar não existe é de extrema importância pois assim o usuário terá conhecimento do ocorrido. No nosso cenário atual isso não está acontecendo, o aviso é informado apenas na ferramenta de desenvolvimento do navegador. Para acessa-la basta aperta F12 ou botão direito do mouse e selecionar inspecionar.

Dentro do nosso Routes iremos criar outra rota com o valor do path sendo * (asterisco). Assim tudo que não estiver listado nas rotas cairá para essa com asterisco.

//src/App.jsx
<Route path="*" element={<PageNotFound />} />
//src/components/PageNotFound.jsx
import React from 'react'

const PageNotFound = () => {
  return (
    <div>
      Página não encontrada
    </div>
  )
}

export default PageNotFound;

Após essas modificações o resultado ao colocar uma url que não existe em nossas rotas é o da imagem acima.

Nesse postagem, vimos os componentes do react router: Routes, Route, Link, NavLink e Outlet, rotas dinâmicas e rotas aninhadas e por ultimo rota para página inexistente.

Referência: React Router