useState
), consolidando os conceitos fundamentais de desenvolvimento com React.npm create vite@latest meu-catalogo-react --template react
cd meu-catalogo-react
npm install
npm run dev
O navegador abrirá emhttp://localhost:5173
src/
├── App.jsx
├── components/
│ └── Produto.jsx
Produto.jsx
// src/components/Produto.jsx
function Produto({ nome, preco }) {
return (
<div style={{ border: "1px solid #ccc", padding: "10px", marginBottom: "10px" }}>
<h3>{nome}</h3>
<p>Preço: R$ {preco}</p>
</div>
);
}
export default Produto;
App.jsx
import { useState } from 'react';
import Produto from './components/Produto';
function App() {
const [produtos, setProdutos] = useState([
{ id: 1, nome: "Notebook", preco: 3500 },
{ id: 2, nome: "Mouse", preco: 150 }
]);
const [novoNome, setNovoNome] = useState('');
const [novoPreco, setNovoPreco] = useState('');
function adicionarProduto() {
const novo = {
id: produtos.length + 1,
nome: novoNome,
preco: parseFloat(novoPreco)
};
setProdutos([...produtos, novo]);
setNovoNome('');
setNovoPreco('');
}
return (
<div style={{ padding: '20px' }}>
<h1>Catálogo de Produtos</h1>
<input
type="text"
placeholder="Nome do produto"
value={novoNome}
onChange={(e) => setNovoNome(e.target.value)}
/>
<input
type="number"
placeholder="Preço"
value={novoPreco}
onChange={(e) => setNovoPreco(e.target.value)}
/>
<button onClick={adicionarProduto}>Adicionar Produto</button>
<hr />
{produtos.map((p) => (
<Produto key={p.id} nome={p.nome} preco={p.preco} />
))}
</div>
);
}
export default App;
Produto
props
useState
.map()
para renderizaçãonpm install react-router-dom
src/
├── App.jsx
├── main.jsx
├── pages/
│ ├── Home.jsx
│ ├── Usuarios.jsx
│ └── UsuarioDetalhe.jsx
main.jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import App from './App';
import Usuarios from './pages/Usuarios';
import UsuarioDetalhe from './pages/UsuarioDetalhe';
ReactDOM.createRoot(document.getElementById('root')).render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
<Route path="/usuarios" element={<Usuarios />} />
<Route path="/usuarios/:id" element={<UsuarioDetalhe />} />
</Routes>
</BrowserRouter>
);
App.jsx
)import { Link } from 'react-router-dom';
function App() {
return (
<div style={{ padding: 20 }}>
<h1>Bem-vindo!</h1>
<p>Esta é a página inicial.</p>
<Link to="/usuarios">Ver lista de usuários</Link>
</div>
);
}
export default App;
Usuarios.jsx
(consome API externa)import { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
function Usuarios() {
const [usuarios, setUsuarios] = useState([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then(resp => resp.json())
.then(dados => setUsuarios(dados));
}, []);
return (
<div style={{ padding: 20 }}>
<h2>Lista de Usuários</h2>
{usuarios.map(user => (
<div key={user.id} style={{ marginBottom: 10 }}>
<strong>{user.name}</strong> - {user.email}
<br />
<Link to={`/usuarios/${user.id}`}>Ver detalhes</Link>
</div>
))}
</div>
);
}
export default Usuarios;
UsuarioDetalhe.jsx
import { useParams } from 'react-router-dom';
import { useEffect, useState } from 'react';
function UsuarioDetalhe() {
const { id } = useParams();
const [usuario, setUsuario] = useState(null);
useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/users/${id}`)
.then(resp => resp.json())
.then(dados => setUsuario(dados));
}, [id]);
if (!usuario) return <p>Carregando...</p>;
return (
<div style={{ padding: 20 }}>
<h2>Detalhes de {usuario.name}</h2>
<p>Email: {usuario.email}</p>
<p>Telefone: {usuario.phone}</p>
<p>Website: {usuario.website}</p>
<p>Empresa: {usuario.company.name}</p>
</div>
);
}
export default UsuarioDetalhe;
react-router-dom
useState
e useEffect
fetch
useParams
)npm create vite@latest usuarios-app --template react
cd usuarios-app
npm install
npm run dev
npm install react-router-dom
src/
├── main.jsx
├── App.jsx
├── pages/
│ ├── Home.jsx
│ ├── Usuarios.jsx
│ └── UsuarioDetalhe.jsx
main.jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import App from './App';
import Usuarios from './pages/Usuarios';
import UsuarioDetalhe from './pages/UsuarioDetalhe';
ReactDOM.createRoot(document.getElementById('root')).render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
<Route path="/usuarios" element={<Usuarios />} />
<Route path="/usuarios/:id" element={<UsuarioDetalhe />} />
</Routes>
</BrowserRouter>
);
App.jsx
)import { Link } from 'react-router-dom';
function App() {
return (
<div style={{ padding: 20 }}>
<h1>Bem-vindo!</h1>
<p>Esta é a página inicial do sistema.</p>
<Link to="/usuarios">Ver lista de usuários</Link>
</div>
);
}
export default App;
Usuarios.jsx
)import { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
function Usuarios() {
const [usuarios, setUsuarios] = useState([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then(resp => resp.json())
.then(dados => setUsuarios(dados));
}, []);
return (
<div style={{ padding: 20 }}>
<h2>Usuários</h2>
{usuarios.map(user => (
<div key={user.id} style={{ marginBottom: 10 }}>
<strong>{user.name}</strong><br />
Email: {user.email}<br />
<Link to={`/usuarios/${user.id}`}>Ver detalhes</Link>
<hr />
</div>
))}
</div>
);
}
export default Usuarios;
UsuarioDetalhe.jsx
)import { useParams } from 'react-router-dom';
import { useEffect, useState } from 'react';
function UsuarioDetalhe() {
const { id } = useParams();
const [usuario, setUsuario] = useState(null);
useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/users/${id}`)
.then(resp => resp.json())
.then(dados => setUsuario(dados));
}, [id]);
if (!usuario) return <p>Carregando...</p>;
return (
<div style={{ padding: 20 }}>
<h2>Detalhes de {usuario.name}</h2>
<p><strong>Email:</strong> {usuario.email}</p>
<p><strong>Telefone:</strong> {usuario.phone}</p>
<p><strong>Site:</strong> {usuario.website}</p>
<p><strong>Empresa:</strong> {usuario.company.name}</p>
</div>
);
}
export default UsuarioDetalhe;
useEffect
)fetch()
para fazer uma requisição HTTP GETuseState
)Usuarios.jsx
https://jsonplaceholder.typicode.com/users
useState
– Armazena os usuáriosconst [usuarios, setUsuarios] = useState([]);
useEffect
– Executa ao carregar a páginauseEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then(resp => resp.json())
.then(dados => setUsuarios(dados));
}, []);
fetch()
faz a chamada HTTP GET para a URL da APIresp.json()
) converte a resposta para um objeto JavaScriptsetUsuarios(dados)
atualiza o estado, o que faz o React re-renderizar a interface com os novos dados.map()
{usuarios.map(user => (
<div key={user.id}>
<strong>{user.name}</strong><br />
Email: {user.email}<br />
</div>
))}
usuarios
está preenchido com dados reais, usamos .map()
para exibir cada usuário dinamicamente na interface.┌────────────────────────────┐
│ Componente │
│ React (SPA) │
└────────────┬───────────────┘
│
│ Montagem do componente
▼
┌────────────────────────────┐
│ useEffect() │
│ Dispara requisição fetch │
└────────────┬───────────────┘
│
│ Requisição HTTP GET
▼
┌────────────────────────────┐
│ API Externa │
│ (jsonplaceholder.typicode) │
└────────────┬───────────────┘
│
│ Resposta JSON
▼
┌────────────────────────────┐
│ setState() │
│ Atualiza estado com dados │
└────────────┬───────────────┘
│
│ Re-renderização do componente
▼
┌────────────────────────────┐
│ Interface Atualizada │
│ Dados exibidos na tela │
└────────────────────────────┘
useEffect
é executado.useEffect
, é realizada uma requisição HTTP GET utilizando fetch
para a API externa.useState
.useEffect
e useState
, a requisição e resposta da API, e a atualização da interface com os dados obtidos.<button onClick={handleClick}>Clique em mim</button>
<button onClick={() => handleClick('argumento')}>Clique em mim</button>