Implementando rotas no react com react-router-dom

Olá galera.

Gostamos muito das funcionalidades do React e a forma em que renderiza as páginas.

Mas como podemos chamar nossos componentes individualmente ou componentes aninhados?

O objetivo desse passo a passo é mostrar a facilidade do roteamento com o uso do react-router-dom.

Os códigos desse artigo foram criados com base na documentação do react-router-dom link abaixo.

https://reactrouter.com/docs/en/v6/getting-started/tutorial

Fiz algumas alterações como separar o css do javascript.

Criando o projeto React inicial:

npx create-react-app 1react-router

Explicando:

Usei 1react-router porque facilita o acesso a pasta do projeto. Se você seguir esse modelo para entrar na pasta basta digitar.

cd 1r+TAB e aí não precisa escrever o restante do nome da pasta beleza.

Depois de criar o projeto e entrar na pasta. Digite:

npm install react-router-dom.

npm start

Verifique se tá tudo beleza e seu package.json está como abaixo:

{

  "name": "1react-router",

  "version": "0.1.0",

  "private": true,

  "dependencies": {

    "react": "^18.2.0",

    "react-dom": "^18.2.0",

    "react-router-dom": "^6.3.0",

    "react-scripts": "0.9.5"

  },

  "scripts": {

    "start": "react-scripts start",

    "build": "react-scripts build",

    "test": "react-scripts test --env=jsdom",

    "eject": "react-scripts eject"

  }

}

Se não estiver copie esse acima cole no seu e rode: npm install.

Depois de deixar tudo como acima...

Vamos alterar o arquivo App.js na pasta src.

O arquivo original tem várias coisas que não vamos precisar, por isso apague tudo e vamos criar um do zero, como abaixo:

export default function App() {

  return (

    <div>

      <h1>Bookkeeper!</h1>

    </div>

  );

}

Modifique também o arquivo src/index.js

Pode deixar como abaixo:

import ReactDOM from "react-dom/client";

import App from "./App";

const root = ReactDOM.createRoot(

  document.getElementById("root")

);

root.render(<App />);

Agora em src/index.js (ou main.js) vamos importar BorwserRouter e envolver o componente App dentro dele. Veja abaixo:

import ReactDOM from "react-dom/client";

import { BrowserRouter } from "react-router-dom";

import App from "./App";


const root = ReactDOM.createRoot(

  document.getElementById("root")

);

root.render(

  <BrowserRouter>

    <App />

  </BrowserRouter>

);


Vamos colocar dois links dentro de src/App.js

import { Link } from "react-router-dom";

import './App.css';

export default function App() {

  return (

    <div>

      <h1>Bookkeeper</h1>

      <nav>

        <Link to="/invoices">Invoices</Link> |{" "}

        <Link to="/expenses">Expenses</Link>

      </nav>

    </div>

  );

}


Visto que já fizemos o importe acima remova o conteudo de App.css e coloque o seguinte:

nav{

border-bottom: solid 1px;

padding-bottom: 1rem;

}

main{

padding: 1rem;

}


Agora crie os dois componentes na pasta como abaixo (crie a pasta routes se ainda não criou):

src/routes/invoices.jsx

src/routes/expenses.jsx

Para facilitar as coisas depois crie também os arquivos css:

src/routes/invoices.css

src/routes/expenses.css


Vai ficar mais fácil fazer a manutenção depois no css bem como acrescentar mais detalhes do front.


Agora que defininimos os componentes Invoices e Expences que serão chamados no roteamento, vamos criá-los na pasta src/routes.

export default function Expenses() {

  return (

    <main style={{ padding: "1rem 0" }}>

      <h2>Expenses</h2>

    </main>

  );

}


export default function Invoices() {

  return (

    <main style={{ padding: "1rem 0" }}>

      <h2>Invoices</h2>

    </main>

  );

}


Conteúdo css equivalentes:

main{

padding: 1rem 0;

}


Agora vamos configurar as rotas em index.js ou main.js:

import ReactDOM from "react-dom/client";

import {

  BrowserRouter,

  Routes,

  Route,

} from "react-router-dom";

import App from "./App";

import Expenses from "./routes/expenses";

import Invoices from "./routes/invoices";


const root = ReactDOM.createRoot(

  document.getElementById("root")

);

root.render(

  <BrowserRouter>

    <Routes>

      <Route path="/" element={<App />} />

      <Route path="expenses" element={<Expenses />} />

      <Route path="invoices" element={<Invoices />} />

    </Routes>

  </BrowserRouter>

);


Observe que a home central ("/") vai ser renderizado App e em "/expenses" será renderizado o componente Expenses.


Se você testar agora seus links verá que seu layout não se tornou persistente.


Os elementos App Expenses e Invoices são irmãos. Vamos tornar App pai dos demais, veja abaixo a alteração em index.js (ou main.js)


import ReactDOM from "react-dom/client";

import {

  BrowserRouter,

  Routes,

  Route,

} from "react-router-dom";

import App from "./App";

import Expenses from "./routes/expenses";

import Invoices from "./routes/invoices";


const root = ReactDOM.createRoot(

  document.getElementById("root")

);

root.render(

  <BrowserRouter>

    <Routes>

      <Route path="/" element={<App />}>

        <Route path="expenses" element={<Expenses />} />

        <Route path="invoices" element={<Invoices />} />

      </Route>

    </Routes>

  </BrowserRouter>

);


Observe que App envolveu os demais elementos.


Agora para que a persistencia do layout funcone precisamos chamar Outlet em App.js na rota pai.


import { Outlet, Link } from "react-router-dom";

import './App.css';

export default function App() {

  return (

    <div>

      <h1>Bookkeeper</h1>

      <nav>

        <Link to="/invoices">Invoices</Link> |{" "}

        <Link to="/expenses">Expenses</Link>

      </nav>

      <Outlet />

    </div>

  );

}


Agora clique novamente no link e veja que a rota pai tornou-se presistente enquanto ocorre a troca dos elementos filhos.


Agora imagine uma aplicação que retorna dados de servidores ou banco de dados. É possível linkar esses dados individualmente rotear.

Vamos criar uma api fake aqui crie o arquivo data.js na pasta src com o conteúdo abaixo.

let invoices = [

  {

    name: "Santa Monica",

    number: 1995,

    amount: "$10,800",

    due: "12/05/1995",

  },

  {

    name: "Stankonia",

    number: 2000,

    amount: "$8,000",

    due: "10/31/2000",

  },

  {

    name: "Ocean Avenue",

    number: 2003,

    amount: "$9,500",

    due: "07/22/2003",

  },

  {

    name: "Tubthumper",

    number: 1997,

    amount: "$14,000",

    due: "09/01/1997",

  },

  {

    name: "Wide Open Spaces",

    number: 1998,

    amount: "$4,600",

    due: "01/27/1998",

  },

];


export function getInvoices() {

  return invoices;

}


Faça o importe em invoices.jsx:

import { Link } from "react-router-dom";

import { getInvoices } from "../data";


export default function Invoices() {

  let invoices = getInvoices();

  return (

    <div>

      <nav>

        {invoices.map((invoice) => (

          <Link

            to={`/invoices/${invoice.number}`}

            key={invoice.number}

          >

            {invoice.name}

          </Link>

        ))}

      </nav>

    </div>

  );

}

Atualize o seu css equivalente invoices.css:


div{

display: flex;

}

main{

padding: 1rem 0;

}

nav{

border-right: solid 1px;

padding: 1rem;

}

.links{

display: block; 

margin: 1rem 0; 

}


Se você clicar em um link de fatura nesse ponto não retorna nada. Vamos corrigir isso e avisar o leitor de algum erro:

Chame um elemento que retornará em caso de uma requisição de rota indefinida. Altere isso em index.js:

    <Route

      path="*"

      element={

        <main>

          <p>There's nothing here!</p>

        </main>

      }

    />

altere seu index.css para: 

body {

  margin: 0;

  padding: 0;

  font-family: sans-serif;

}

main{

padding: 1rem;


    

Agora vamos rotear um dado retornado do banco de dados. Em nosso caso aquela api fake.

Para isso crie mais um componente src/routes/invoice.jsx com o seguinte conteúdo:

export default function Invoice() {

  return <h2>Invoice #???</h2>;

}


Insira esse componente como filho de Invoices.

<Routes>

  <Route path="/" element={<App />}>

    <Route path="expenses" element={<Expenses />} />

    <Route path="invoices" element={<Invoices />}>

      <Route path=":invoiceId" element={<Invoice />} />

    </Route>

    <Route

      path="*"

      element={

        <main style={{ padding: "1rem" }}>

          <p>There's nothing here!</p>

        </main>

      }

    />

  </Route>

</Routes>


Agora criamos uma url que corresponde ao item retornado.

Adicionamos também uma segunda camada de aninhamento que fica como abaixo:

App pai de invoices e invoice filho de invoices.


Se você clicar em uma fatura ela ainda não aparece.

Então vamos chamar Outlet novamente agora na rota filha de Invoices.


import React from 'react';

import './invoices.css';

import { Outlet, Link } from "react-router-dom";

import { getInvoices } from "../data";


export default function Invoices() {

let invoices = getInvoices();

return (

<div style={{ display: "flex" }}>

<nav>

{invoices.map((invoice) => (

<Link className="links"

to={`/invoices/${invoice.number}`}

key={invoice.number}>

{invoice.name}

</Link>

))}

</nav>

<Outlet />

</div>

);

}


Atualize seu invoices.css

div{

display: flex;

}

main{

padding: 1rem 0;

}

nav{

border-right: solid 1px;

padding: 1rem;

}

.links{

display: block; 

margin: 1rem 0;

}

Atualize seu invoice.jsx como abaixo para pegar o parametro retornado pela url:

import { useParams } from "react-router-dom";

export default function Invoice() {

  let params = useParams();

  return <h2>Invoice: {params.invoiceId}</h2>;

}

Agora em data.js adicione uma nova função para pesuisar faturas pelo número:

export function getInvoice(number) {

  return invoices.find(

    (invoice) => invoice.number === number

  );

}

Agora voltando ao componente do arquivo invoice.jsx usamos o parametro para procurar uma fatura e exibir mais informações:

import React from 'react';

import { useParams} from 'react-router-dom';

import './invoice.css';

import { getInvoice} from '../data';

export default function Invoice(){

let params = useParams();

let invoice = getInvoice(parseInt(params.invoiceId, 10));

return (

<main style={{  }}>

<h2>Total Due: {invoice.amount}</h2>

<p>

{invoice.name}: {invoice.number}

</p>

<p>Due Date: {invoice.due}</p>

</main>

);

}


Fechando...

O que foi desenvolvido aqui com a ajuda da documentação pode ser conferido nesse vídeo do youtube.

https://youtu.be/luyfv7r1fe4

Os arquivos estão nesse repositório no github.

https://github.com/aondenet-sinval/react-router-basic.git

Com certeza há muito mais coisas a aprender sobre rect-router-dom essa biblioteca é fantastica.

Em breve irei postar mais algumas coisas interessantes sobre essa poderosa biblioteca React.

NOVA PLANILHA MEI OU PEQUENA EMPRESA ATUALIZAÇÃO


 

Essa atualização da planilha Frente de caixa com Libreoffice Calc agora possui a opção de uso com os bancos de dados: MySql ou HSQL. Ao comprar envie pelo formulário a opção.
A instalação e configuração do banco de dados será feita remotamente.

TELAS DE CADASTROS DO SISTEMA FRENTE DE CAIXA PARA MEI OU PEQUENA EMPRESA

Cadastros:
Clientes, Fornecedores, Funcionários, Estoque e Despesas
Visualização gráfica e em relatórios de todos os dados cadastrados do negócio.


BANCO DE DADOS: Mysql.
Código: 9090