Introdução
Eu tenho mais familiaridade com o backend, mas por gostar muito de javascript, o ReactJS sempre está nas minhas trilhas de aprendizado.
Buscando mais informações sobre as rotas, algumas questões que não ficavam claras para mim era o carregamento de telas e navegação entre elas com toda aquela parafernalha que o front precisa carregar: css, js, libs, componentes, etc, sendo que nem sempre existe a necessidade de ir no backend para resolver algo.
Este post pode ser básico se você já possui um conhecimento sólido do ReactJS, mas pode auxiliar alguém que esteja iniciando.
Nesta publicação você vai ver
Objetivo
Vamos construir uma aplicação com carregamento de duas telas: clientes e produtos e permitir a navegação entre essas elas sem o carregamento total da página. A tela de clientes possuirá uma listagem permitindo a visualização dos detalhes de cada cliente com uma navegação interna.
O repositório completo fica neste link: https://github.com/tiagosabadini/navegacao-react-router-dom6.
Criando a aplicação
Antes de tudo, vamos criar nossa aplicação. E, dentro da pasta do novo projeto, vamos instalar a versão 6 do react-router-dom.
npx create-react-app navegacao-react
cd navegacao-react
npm install react-router-dom@6
Acesse o projeto com seu editor de códigos favorito e deixe dentro da pasta src
apenas os arquivos App.js
e index.js
com o código abaixo. Rode o comando npm start
para ver se está tudo certo no navegador.
//App.js
export default function App() {
return (
<div>
<h1>Gestão de Lojinha</h1>
</div>
);
}
//index.js
import { render } from "react-dom";
import App from "./App";
const rootElement = document.getElementById("root");
render(<App />, rootElement);
Sem surpresas até aqui, apenas um texto impresso no navegador.
Conectando a URL
Agora precisamos conectar nossa aplicação com a URL do navegador, importando o BrowserRouter
e envolvendo nosso App
com ele.
import { render } from "react-dom";
import { BrowserRouter } from "react-router-dom";
import App from "./App";
const rootElement = document.getElementById("root");
render(
<BrowserRouter>
<App />
</BrowserRouter>,
rootElement
);
Adicionando links e rotas
Agora para vermos algumas coisas funcionando por aqui, vamos adicionar alguns links e rotas na nossa aplicação. Importe o componente Link
, adicione no seu App.js
e crie links para as páginas de clientes e produtos.
//App.js
import { Link } from "react-router-dom";
export default function App() {
return (
<div>
<h1>Gestão de Lojinha</h1>
<nav
style={{
borderBottom: "solid 2px green",
paddingBottom: "1rem",
}}
>
<Link to="/clientes">Clientes</Link> |{" "}
<Link to="/produtos">Produtos</Link>
</nav>
</div>
);
}
//index.js
import { render } from "react-dom";
import { BrowserRouter } from "react-router-dom";
import App from "./App";
const rootElement = document.getElementById("root");
render(
<BrowserRouter>
<App />
</BrowserRouter>,
rootElement
);
Perceba que a navegação funciona, o link no navegador é alterado conforme o clique do usuário e a tela não é recarregada. Agora precisamos criar as rotas e apontar para os componentes corretos.
As rotas serão criadas dentro do index.js
e informará ao React quais componentes serão carregados quando uma determinada rota for acionada.
Crie uma pasta chamada routes
e adicione os arquivos clientes.js
e produtos.js
.
//./routes/clientes.js
export default function Clientes(){
return (
<h1>Clientes</h1>
);
}
//./routes/produtos.js
export default function Produtos(){
return (
<h1>Produtos</h1>
);
}
Já no arquivo index.js
vamos importar Routes
, Route
e os componentes Clientes
e Produtos
que acabamos de criar.
import { render } from "react-dom";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import App from "./App";
import Clientes from "./routes/clientes";
import Produtos from "./routes/produtos";
const rootElement = document.getElementById("root");
render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
<Route path="/clientes" element={<Clientes />} />
<Route path="/produtos" element={<Produtos />} />
</Routes>
</BrowserRouter>,
rootElement
);
A navegação ficou mais interessante agora, mas veja que ao acessar a tela de clientes ou produtos, o layout padrão some. Isso acontece porque o layout com o menu está apenas no componente App
e não é compartilhado entre as demais telas da aplicação.
Você pode pensar em repetir o menu em todos os componentes ou carregar os demais componentes dentro do componente principal App
para tentar resolver esse problema, mas podemos resolver de uma forma mais interessante.
Rotas aninhadas
Para compartilhar o layout do App
vamos colocar as rotas clientes
e produtos
dentro de index.js
como filhas da Rota com path “/”.
Dentro de App
importe o componente Outlet
e adicione-o antes do fechamento da última <div>
.
import { render } from "react-dom";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import App from "./App";
import Clientes from "./routes/clientes";
import Produtos from "./routes/produtos";
const rootElement = document.getElementById("root");
render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />}>
<Route path="/clientes" element={<Clientes />} />
<Route path="/produtos" element={<Produtos />} />
</Route>
</Routes>
</BrowserRouter>,
rootElement
);
import { Link, Outlet } from "react-router-dom";
export default function App() {
return (
<div>
<h1>Gestão de Lojinha</h1>
<nav
style={{
borderBottom: "solid 2px green",
paddingBottom: "1rem",
}}
>
<Link to="/clientes">Clientes</Link> |{" "}
<Link to="/produtos">Produtos</Link>
</nav>
<Outlet />
</div>
);
}
As rotas aninhadas possuem paths relativos. Quando criamos uma rota pai com path “admin”, por exemplo, as rotas filho serão sempre “admin/path-da-rota”. O prefixo “admin” está implícito, não é necessário incluir no path das rotas filho.
Listando clientes
Normalmente a gente busca dados de algum servidor, mas vamos colocar alguns dados fake aqui para focarmos na navegação e rotas.
Adicione um arquivo data.js
na raiz da pasta src
e importe o arquivo dentro do componente routes/clientes.js
.
let clientes = [
{
"id": 1,
"nome": "joão da silva",
"idade": 22,
"local_nascimento": "rio de janeiro",
},
{
"id": 2,
"nome": "maria helena",
"idade": 32,
"local_nascimento": "são paulo",
},
{
"id": 3,
"nome": "jonas almeida",
"idade": 44,
"local_nascimento": "minas gerais",
},
{
"id": 4,
"nome": "juliana maria talgaz",
"idade": 26,
"local_nascimento": "minas gerais",
},
{
"id": 5,
"nome": "tereza maria",
"idade": 54,
"local_nascimento": "minas gerais",
},
{
"id": 6,
"nome": "jober joelson silva",
"idade": 28,
"local_nascimento": "são paulo",
},
{
"id": 7,
"nome": "mariana silva",
"idade": 20,
"local_nascimento": "rio de janeiro",
},
{
"id": 8,
"nome": "roberto manejo",
"idade": 21,
"local_nascimento": "rio de janeiro",
},
];
export function getClientes() {
return clientes;
}
O componente clientes.js
receberá agora um loop com map()
para imprimir os links e permitir a exibição dos detalhes de cada cliente quando forem clicados.
import {Link} from 'react-router-dom';
import {getClientes} from '../data';
export default function Clientes(){
let clientes = getClientes();
return (
<div style={{display: "flex"}}>
<nav
style={{
borderRight: "solid 2px green",
padding: "1rem",
marginRight: "2rem",
}}
>
{
clientes.map((cliente) => {
return <Link
style={{
display: "block",
margin: "1rem 0",
}}
to={`/clientes/${cliente.id}`} key={cliente.id}>
{cliente.nome}
</Link>
})
}
</nav>
</div>
);
}
Agora quando clicamos no link de cada cliente, a tela fica em branco. Para resolver isso vamos repetir o processo que fizemos lá no início. Criando um aninhamento para a rota de clientes e importando Outlet
dentro de Clientes
para compartilhar o layout do componente principal.
Para exibirmos os detalhes de cada cliente, vamos criar um novo componente dentro de routes
chamado cliente.js
. Ele vai receber os parâmetros da URL e buscar os detalhes do cliente selecionado.
import {useParams} from 'react-router-dom';
import {getCliente} from '../data';
export default function Cliente(){
const params = useParams();
const cliente = getCliente(parseInt(params.clienteId, 10));
return (
<main style={{ padding: "1rem" }}>
<h2>Nome: {cliente.nome}</h2>
<p>
{cliente.nome}: #{cliente.id}
</p>
<p>Idade: {cliente.idade}</p>
<p>Local de Nascimento: {cliente.local_nascimento}</p>
</main>
);
}
Apenas criar o componente não vai fazer a aplicação funcionar, precisamos adicionar a rota para que o React saiba o que fazer quando esse link for acionado.
import { render } from "react-dom";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import App from "./App";
import Clientes from "./routes/clientes";
import Cliente from "./routes/cliente";
import Produtos from "./routes/produtos";
const rootElement = document.getElementById("root");
render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />}>
<Route path="clientes" element={<Clientes />}>
<Route path=":clienteId" element={<Cliente />} />
</Route>
<Route path="produtos" element={<Produtos />} />
</Route>
</Routes>
</BrowserRouter>,
rootElement
);
Conclusão
Espero que esta postagem tenha contribuído para você. Caso queira acessar o repositório completo, veja este link: https://github.com/tiagosabadini/navegacao-react-router-dom6.
Conhecimento é algo que ninguém pode tirar de você e quando é compartilhado não se perde, multiplica.