React do Zero: Criando um Site com 21 Exemplos
React é uma biblioteca JavaScript para criar páginas web interativas. Ela divide a página em pedaços pequenos chamados componentes. Cada componente recebe dados e devolve uma parte da página. Este artigo leva você do primeiro texto exibido até montar um pequeno site com menu, cartões alimentados por dados e rodapé. Cada exemplo é um arquivo real que foi executado, e a saída mostrada é a saída de verdade.
O que você precisa
Você precisa de Node.js 18 ou mais recente, conhecimento básico de JavaScript e qualquer editor. Instale os pacotes com `npm install [email protected] [email protected]` e execute cada exemplo com o testador deste artigo. Os exemplos que têm passos de clicar em um botão rodam em um navegador simulado criado com jsdom.
Ilustração
Exemplo 1: Exibindo o primeiro texto
Componentes são funções que devolvem JSX. Este exemplo cria um título e o transforma em HTML com renderToStaticMarkup.
import React from "react";
export function App() {
return <h1>Olá, React</h1>;
}
Saída real
<h1>Olá, React</h1>
Exemplo 2: Exibindo uma lista com map
Use map para transformar um array em um li para cada item. Quando os dados mudam, a página acompanha a mudança sem que você edite o HTML.
import React from "react";
const fruits = ["Durian", "Mangostão", "Manga"];
export function App() {
return (
<ul>
{fruits.map(f => <li key={f}>{f}</li>)}
</ul>
);
}
Saída real
<ul><li>Durian</li><li>Mangostão</li><li>Manga</li></ul>
Exemplo 3: Passando props para um componente
Props são os dados que um componente pai entrega ao filho. O mesmo componente pode ser reutilizado com dados diferentes.
import React from "react";
function Greeting({ name, age }) {
return <p>Olá {name}, {age} anos</p>;
}
export function App() {
return (
<div>
<Greeting name="Budi" age={20} />
<Greeting name="Siti" age={22} />
</div>
);
}
Saída real
<div><p>Olá Budi, 20 anos</p><p>Olá Siti, 22 anos</p></div>
Exemplo 4: Renderização condicional
Use && e o operador ternário para escolher o que aparece na página.
import React from "react";
function Status({ online }) {
return (
<div>
{online ? <span>Online</span> : <span>Offline</span>}
{online && <em>Pronto para conversar</em>}
</div>
);
}
export function App() {
return <Status online={true} />;
}
Saída real
<div><span>Online</span><em>Pronto para conversar</em></div>
Exemplo 5: Fragment
Quando você não quer uma div extra, envolva vários elementos com <> ... </>.
import React from "react";
function Header() {
return (
<>
<h2>Título</h2>
<p>Sem div envolvendo</p>
</>
);
}
export function App() {
return <Header />;
}
Saída real
<h2>Título</h2><p>Sem div envolvendo</p>
Exemplo 6: Keys em uma tabela
Monte uma tabela a partir dos dados e use o id como key para que o React acompanhe cada linha.
import React from "react";
const students = [
{ id: 1, name: "Budi", score: 85 },
{ id: 2, name: "Siti", score: 72 },
];
export function App() {
return (
<table>
<tbody>
{students.map(s => (
<tr key={s.id}>
<td>{s.name}</td>
<td>{s.score}</td>
</tr>
))}
</tbody>
</table>
);
}
Saída real
<table><tbody><tr><td>Budi</td><td>85</td></tr><tr><td>Siti</td><td>72</td></tr></tbody></table>
Exemplo 7: Estilo como objeto
O estilo no React recebe um objeto com nomes em camelCase, como backgroundColor e borderRadius.
import React from "react";
const box = {
padding: 12,
backgroundColor: "#eef4ff",
borderRadius: 8,
color: "#1a1a1a",
};
export function App() {
return <div style={box}>Caixa estilizada com um objeto de estilo</div>;
}
Saída real
<div style="padding:12px;background-color:#eef4ff;border-radius:8px;color:#1a1a1a">Caixa estilizada com um objeto de estilo</div>
Exemplo 8: children
Coloque JSX entre a tag de abertura e a de fechamento, para que o componente possa envolver qualquer conteúdo.
import React from "react";
function Card({ title, children }) {
return (
<section>
<h3>{title}</h3>
<div>{children}</div>
</section>
);
}
export function App() {
return (
<Card title="Notícias">
<p>Conteúdo enviado para children</p>
</Card>
);
}
Saída real
<section><h3>Notícias</h3><div><p>Conteúdo enviado para children</p></div></section>
Exemplo 9: Contador com state
useState guarda um valor que muda. Chamar o setter faz o React renderizar de novo. Este exemplo clica no botão duas vezes e mostra a mudança.
import React, { useState } from "react";
export function App() {
const [count, setCount] = useState(0);
return (
<div>
<p data-out>Contagem: {count}</p>
<button id="inc" onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
export const steps = ["#inc", "#inc"];
Saída real
Texto inicial: Contagem: 0
Após o 1º clique: Contagem: 1
Após o 2º clique: Contagem: 2
Exemplo 10: Input controlado
O valor do input é controlado pelo state e atualizado no onChange a cada tecla digitada. Este exemplo mostra o valor inicial, com zero caracteres.
import React, { useState } from "react";
export function App() {
const [text, setText] = useState("");
return (
<div>
<input id="box" value={text} onChange={e => setText(e.target.value)} />
<p>Digitado: {text.length} caracteres</p>
</div>
);
}
Saída real
<div><input id="box" value=""/><p>Digitado: 0 caracteres</p></div>
Exemplo 11: Interruptor liga/desliga
Guarde um valor booleano no state e inverta-o com !on a cada clique.
import React, { useState } from "react";
export function App() {
const [on, setOn] = useState(false);
return (
<div>
<p data-out>{on ? "Ligado" : "Desligado"}</p>
<button id="toggle" onClick={() => setOn(!on)}>Alternar</button>
</div>
);
}
export const steps = ["#toggle", "#toggle"];
Saída real
Texto inicial: Desligado
Após o 1º clique: Ligado
Após o 2º clique: Desligado
Exemplo 12: useEffect
Efeitos rodam depois da renderização. Use-os para tarefas como carregar dados ou preparar algo quando o componente aparece pela primeira vez.
import React, { useEffect, useState } from "react";
export function App() {
const [message, setMessage] = useState("Carregando");
useEffect(() => {
setMessage("Carregado (a partir do useEffect)");
}, []);
return <p data-out>{message}</p>;
}
export const steps = [];
Saída real
Texto inicial: Carregado (a partir do useEffect)
Exemplo 13: Formulário que guarda o valor
Leia o conteúdo do input para o state e salve quando o botão for clicado. Este exemplo começa com o nome Budi.
import React, { useState } from "react";
export function App() {
const [name, setName] = useState("Budi");
const [saved, setSaved] = useState("");
return (
<div>
<input value={name} onChange={e => setName(e.target.value)} />
<button id="save" onClick={() => setSaved(name)}>Salvar</button>
<p data-out>Salvo: {saved || "Ainda não há"}</p>
</div>
);
}
export const steps = ["#save"];
Saída real
Texto inicial: Salvo: Ainda não há
Após o 1º clique: Salvo: Budi
Exemplo 14: Lista de tarefas
Adicione itens criando um novo array com spread, em vez de alterar o array antigo.
import React, { useState } from "react";
let nextId = 1;
export function App() {
const [items, setItems] = useState([]);
const add = () => {
const id = nextId++;
setItems([...items, { id, text: "Tarefa nº " + id }]);
};
return (
<div>
<button id="add" onClick={add}>Adicionar tarefa</button>
<ul data-out>{items.map(i => <li key={i.id}>{i.text}</li>)}</ul>
</div>
);
}
export const steps = ["#add", "#add"];
Saída real
Texto inicial:
Após o 1º clique: Tarefa nº 1
Após o 2º clique: Tarefa nº 1Tarefa nº 2
Exemplo 15: Context
Passe um valor de tema para um componente distante, sem enviar props por cada nível.
import React, { createContext, useContext } from "react";
const ThemeContext = createContext("light");
function Button() {
const theme = useContext(ThemeContext);
return <button>Tema: {theme}</button>;
}
export function App() {
return (
<ThemeContext.Provider value="dark">
<Button />
</ThemeContext.Provider>
);
}
Saída real
<button>Tema: dark</button>
Exemplo 16: useReducer
Gerencie um state com vários valores ou ações usando ações e um reducer.
import React, { useReducer } from "react";
function reducer(state, action) {
switch (action.type) {
case "inc": return { count: state.count + 1 };
case "dec": return { count: state.count - 1 };
default: return state;
}
}
export function App() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div>
<p data-out>Valor: {state.count}</p>
<button id="inc" onClick={() => dispatch({ type: "inc" })}>+</button>
<button id="dec" onClick={() => dispatch({ type: "dec" })}>-</button>
</div>
);
}
export const steps = ["#inc", "#inc", "#dec"];
Saída real
Texto inicial: Valor: 0
Após o 1º clique: Valor: 1
Após o 2º clique: Valor: 2
Após o 3º clique: Valor: 1
Exemplo 17: Hook personalizado
Coloque a lógica de state em uma função cujo nome começa com use, para poder reutilizá-la.
import React, { useState } from "react";
function useCounter(start) {
const [count, setCount] = useState(start);
return { count, increment: () => setCount(c => c + 1) };
}
export function App() {
const { count, increment } = useCounter(10);
return (
<div>
<p data-out>Valor atual: {count}</p>
<button id="inc" onClick={increment}>Somar</button>
</div>
);
}
export const steps = ["#inc"];
Saída real
Texto inicial: Valor atual: 10
Após o 1º clique: Valor atual: 11
Exemplo 18: useMemo
Guarde o resultado de um cálculo pesado e recalcule apenas quando as dependências mudarem.
import React, { useMemo } from "react";
const numbers = [1, 2, 3, 4, 5];
export function App() {
const total = useMemo(() => numbers.reduce((a, b) => a + b, 0), []);
return <p>Soma = {total}</p>;
}
Saída real
<p>Soma = 15</p>
Exemplo 19: Abas
Escolha o conteúdo de um objeto de acordo com a aba que o usuário clicou. Este exemplo alterna entre a aba A e a aba B.
import React, { useState } from "react";
const content = {
a: "Conteúdo da aba A",
b: "Conteúdo da aba B",
};
export function App() {
const [tab, setTab] = useState("a");
return (
<div>
<button id="tab-a" onClick={() => setTab("a")}>Aba A</button>
<button id="tab-b" onClick={() => setTab("b")}>Aba B</button>
<p data-out>{content[tab]}</p>
</div>
);
}
export const steps = ["#tab-b", "#tab-a"];
Saída real
Texto inicial: Conteúdo da aba A
Após o 1º clique: Conteúdo da aba B
Após o 2º clique: Conteúdo da aba A
Exemplo 20: Carregando dados
Carregue os dados quando o componente aparece pela primeira vez, mostre uma mensagem de carregamento e exiba a lista quando terminar.
import React, { useEffect, useState } from "react";
const DATA = ["Budi", "Siti", "Dedi"];
export function App() {
const [loading, setLoading] = useState(true);
const [items, setItems] = useState([]);
const load = () => {
setLoading(true);
setTimeout(() => { setItems(DATA); setLoading(false); }, 0);
};
useEffect(() => { load(); }, []);
return (
<div>
<button id="reload" onClick={load}>Recarregar</button>
<div data-out>{loading ? <p>Carregando...</p> : <ul>{items.map(n => <li key={n}>{n}</li>)}</ul>}</div>
</div>
);
}
export const steps = ["#reload"];
Saída real
Texto inicial: Carregando...
Após o 1º clique: BudiSitiDedi
Exemplo 21: Um pequeno site feito de componentes
Junte tudo em uma única página com cabeçalho e menu, seção de destaque, cartões de serviço gerados a partir de dados e rodapé.
import React from "react";
const menu = ["Início", "Serviços", "Contato"];
const services = [
{ id: 1, name: "Site institucional", price: 15000 },
{ id: 2, name: "Loja virtual", price: 25000 },
];
function Header() {
return (
<header style={{ background: "#1a2b4c", color: "#fff", padding: "12px" }}>
<strong>Empresa Exemplo</strong>
<nav>{menu.map(m => <a key={m} href="#" style={{ marginLeft: 12, color: "#fff" }}>{m}</a>)}</nav>
</header>
);
}
function Hero({ title, subtitle }) {
return (
<section>
<h1>{title}</h1>
<p>{subtitle}</p>
</section>
);
}
function ServiceCard({ name, price }) {
return (
<div style={{ border: "1px solid #ccc", borderRadius: 8, padding: 12, margin: 8 }}>
<h3>{name}</h3>
<p>A partir de R$ {price.toLocaleString("en-US")}</p>
</div>
);
}
function Footer() {
return <footer><small>© 2026 Empresa Exemplo</small></footer>;
}
export function App() {
return (
<div>
<Header />
<main>
<Hero title="Bem-vindo" subtitle="Criamos sites para o seu negócio" />
<div>{services.map(s => <ServiceCard key={s.id} name={s.name} price={s.price} />)}</div>
</main>
<Footer />
</div>
);
}
Saída real
<div><header style="background:#1a2b4c;color:#fff;padding:12px"><strong>Empresa Exemplo</strong><nav><a href="#" style="margin-left:12px;color:#fff">Início</a><a href="#" style="margin-left:12px;color:#fff">Serviços</a><a href="#" style="margin-left:12px;color:#fff">Contato</a></nav></header><main><section><h1>Bem-vindo</h1><p>Criamos sites para o seu negócio</p></section><div><div style="border:1px solid #ccc;border-radius:8px;padding:12px;margin:8px"><h3>Site institucional</h3><p>A partir de R$ 15,000</p></div><div style="border:1px solid #ccc;border-radius:8px;padding:12px;margin:8px"><h3>Loja virtual</h3><p>A partir de R$ 25,000</p></div></div></main><footer><small>© 2026 Empresa Exemplo</small></footer></div>
Próximos passos
Depois, use o React Router para dividir o site em várias páginas, chame uma API real com fetch e use Vite ou Next.js para criar o projeto. Depois que você entender state e props, adicionar recursos se resume a compor mais componentes.
Resumo
O React monta páginas a partir de componentes que recebem props e guardam state. Quando o state muda, o React renderiza de novo apenas a parte afetada. Os 21 exemplos cobrem tudo, desde renderizar um texto até montar um pequeno site completo, e cada saída deste artigo vem de um processo que foi realmente executado.