React do Zero: Criando um Site com 21 Exemplos

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

Como o React funciona: dados e estado entram no componente, que gera HTML
Como o React funciona: dados e estado entram no componente, que gera HTML

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
Ciclo de estado: o clique chama o setter, e então o React renderiza de novo
Ciclo de estado: o clique chama o setter, e então o React renderiza de novo

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.