
React para Iniciantes: Componentes, Estado e o Fluxo de Dados
React revolucionou o desenvolvimento front-end ao introduzir uma abordagem baseada em componentes. Em vez de manipular o DOM diretamente, você descreve o que a interface deve mostrar em cada estado — e o React cuida de sincronizar isso com eficiência. Esta abordagem torna interfaces complexas previsíveis e testáveis.
O que é React, e por que ele existe?
Criado pelo Facebook em 2013, React é uma biblioteca JavaScript para construção de interfaces de usuário. Não é um framework completo: ele se concentra exclusivamente na camada de visualização, deixando roteamento, estado global e requisições HTTP para bibliotecas complementares.
A inovação central do React é o Virtual DOM. Em vez de modificar o DOM do navegador a cada mudança, o React mantém uma representação em memória da árvore de elementos, calcula a diferença (diff) entre estados e aplica apenas as alterações mínimas necessárias. Isso elimina manipulações manuais ineficientes e reduz bugs.
React não impõe arquitetura. Você pode usá-lo em uma página HTML estática via CDN, em um SPA com Vite ou Next.js, ou até embutido em aplicações legadas. Essa flexibilidade é uma de suas maiores forças.
Configuração Mínima com Vite
Para aprender React hoje, a forma mais rápida é usar o Vite. Ele cria um projeto funcional em segundos, com hot module replacement e build otimizado.
# Cria o projeto
npm create vite@latest meu-app -- --template react-ts
# Entra na pasta e instala dependências
cd meu-app
npm install
# Inicia o servidor de desenvolvimento
npm run devA estrutura gerada inclui App.tsx, main.tsx e um index.html. Não há boilerplate excessivo. Você pode começar a editar App.tsx imediatamente e ver as mudanças no navegador em milissegundos.
JSX: JavaScript com Aparência de HTML
JSX é uma extensão de sintaxe que permite escrever elementos HTML dentro de JavaScript. Não é obrigatório — você pode usar React.createElement diretamente — mas JSX torna o código legível e familiar para quem conhece HTML.
// JSX é transformado em React.createElement pelo compilador
function Saudacao({ nome }: { nome: string }) {
return <h1>Olá, {nome}!</h1>;
}
// Equivalente sem JSX
function SaudacaoSemJSX({ nome }: { nome: string }) {
return React.createElement("h1", null, `Olá, ${nome}!`);
}Regras importantes do JSX: retorne um único elemento raiz (use <>...</> para fragmentos), use className em vez de class (class é palavra reservada em JS), e envolva expressões em chaves {}.
Componentes: Blocos de Construção
Em React, tudo é componente. Um componente é uma função que recebe propriedades (props) e retorna JSX. A filosofia é dividir a interface em partes independentes, reutilizáveis e isoladas.
// Componente funcional simples
interface BotaoProps {
texto: string;
onClick: () => void;
desabilitado?: boolean;
}
function Botao({ texto, onClick, desabilitado = false }: BotaoProps) {
return (
<button
onClick={onClick}
disabled={desabilitado}
className="px-4 py-2 bg-blue-600 text-white rounded"
>
{texto}
</button>
);
}
// Composição de componentes
function Painel() {
const [contador, setContador] = useState(0);
return (
<div className="p-6 border rounded-lg">
<h2 className="text-xl font-bold">Contador</h2>
<p className="my-2">Valor atual: {contador}</p>
<Botao
texto="Incrementar"
onClick={() => setContador((c) => c + 1)}
/>
</div>
);
}Componentes devem ser puros em relação às props: para os mesmos inputs, sempre retornam os mesmos outputs. Isso torna o comportamento previsível e facilita testes.
Props: Dados de Fora para Dentro
Props (abreviação de properties) são os dados que um componente recebe de seu pai. São read-only: um componente nunca deve modificar suas próprias props. Se precisar mudar algo, ele emite um evento via callback.
interface TarefaProps {
titulo: string;
concluida: boolean;
onToggle: () => void;
onExcluir: () => void;
}
function Tarefa({ titulo, concluida, onToggle, onExcluir }: TarefaProps) {
return (
<li className={concluida ? "line-through text-gray-500" : ""}>
<span onClick={onToggle} className="cursor-pointer">
{titulo}
</span>
<button onClick={onExcluir} aria-label="Excluir tarefa">
×
</button>
</li>
);
}A comunicação entre componentes segue o padrão "dados descem, eventos sobem". O pai passa dados via props; o filho notifica mudanças via callbacks. Isso mantém o fluxo unidirecional e previsível.
Estado Local com useState
Quando um componente precisa lembrar informação entre renderizações, usa-se estado. O hook useState é a forma mais comum de adicionar estado a componentes funcionais.
import { useState } from "react";
function FormularioLogin() {
const [email, setEmail] = useState("");
const [senha, setSenha] = useState("");
const [erro, setErro] = useState<string | null>(null);
function handleSubmit(e: React.FormEvent) {
e.preventDefault();
if (!email.includes("@")) {
setErro("E-mail inválido");
return;
}
setErro(null);
// enviar para API
}
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="E-mail"
/>
<input
type="password"
value={senha}
onChange={(e) => setSenha(e.target.value)}
placeholder="Senha"
/>
{erro && <p className="text-red-600">{erro}</p>}
<button type="submit">Entrar</button>
</form>
);
}useState retorna um par: o valor atual e uma função para atualizá-lo. A atualização é assíncrona e aciona uma nova renderização. Nunca modifique o estado diretamente — sempre use a função setter.
Efeitos Colaterais com useEffect
Componentes React devem ser puros em relação às props. Mas aplicações reais precisam sincronizar com o mundo externo: APIs, DOM, timers, subscriptions. O hook useEffect executa código imperativo após a renderização.
import { useState, useEffect } from "react";
function ListaUsuarios() {
const [usuarios, setUsuarios] = useState<Array<{ id: number; nome: string }>>([]);
const [carregando, setCarregando] = useState(true);
useEffect(() => {
let cancelado = false;
fetch("/api/usuarios")
.then((res) => res.json())
.then((dados) => {
if (!cancelado) {
setUsuarios(dados);
setCarregando(false);
}
});
// Função de cleanup: executada quando o componente desmonta
// ou antes de reexecutar o efeito
return () => {
cancelado = true;
};
}, []); // array vazio = executa apenas na montagem
if (carregando) return <p>Carregando...</p>;
return (
<ul>
{usuarios.map((u) => (
<li key={u.id}>{u.nome}</li>
))}
</ul>
);
}O array de dependências controla quando o efeito executa. [] executa uma vez. [usuarioId] executa quando usuarioId muda. Omitir o array executa a cada renderização — geralmente indesejado. Sempre inclua todas as dependências usadas dentro do efeito.
Efeitos sem cleanup são uma fonte comum de memory leaks e race conditions. Sempre retorne uma função de limpeza para subscriptions, timers, listeners e requisições que podem ser canceladas.
Renderização e Reconciliação
Quando o estado ou as props mudam, o React reexecuta a função do componente. Isso é chamado de renderização. O React então compara o novo JSX com a versão anterior e atualiza apenas os elementos do DOM que realmente mudaram.
Chaves (keys) são essenciais em listas. Elas ajudam o React a identificar quais itens mudaram, foram adicionados ou removidos. Use IDs estáveis, nunca índices de array, que causam bugs sutis quando a ordem muda.
// Correto: ID estável
{itens.map((item) => (
<li key={item.id}>{item.nome}</li>
))}
// Incorreto: índice como key
{itens.map((item, index) => (
<li key={index}>{item.nome}</li>
))}Hooks Adicionais Essenciais
Além de useState e useEffect, React oferece hooks especializados para padrões comuns.
| Hook | Uso principal | Quando usar |
|---|---|---|
| useRef | Referência mutável persistente entre renders | Acesso a elementos DOM, timers, flags de controle |
| useMemo | Memorização de valores computados | Cálculos caros que não precisam refazer a cada render |
| useCallback | Memorização de funções | Evitar recriação de callbacks passados a componentes filhos otimizados |
| useContext | Acesso a valores globais sem prop drilling | Temas, autenticação, preferências de usuário |
| useReducer | Estado complexo com lógica de transição | Formulários multi-campo, máquinas de estado, lógica condensada |
// useRef para acessar input programaticamente
function CampoFoco() {
const inputRef = useRef<HTMLInputElement>(null);
function focar() {
inputRef.current?.focus();
}
return (
<>
<input ref={inputRef} type="text" />
<button onClick={focar}>Focar</button>
</>
);
}Boas Práticas para Iniciantes
- Mantenha componentes pequenos: um componente deve fazer uma coisa bem. Se passar de 150 linhas, considere dividir.
- Extraia lógica em hooks customizados: se um componente usa múltiplos efeitos para carregar dados, crie um useFetch ou similar.
- Evite prop drilling excessivo: se precisa passar dados por mais de 3 níveis, considere Context ou uma biblioteca de estado global.
- TypeScript desde o início: tipar props e estado previne erros bobos e documenta a API do componente.
- Não otimize prematuramente: useMemo e useCallback têm custo. Use apenas quando houver evidência de problema de performance.
Conclusão
React é uma biblioteca com conceitos simples e profundos. Componentes, props e estado formam a base. Hooks adicionam poder sem complexidade desnecessária. O Virtual DOM abstrai manipulações manuais. E o ecossistema oferece soluções maduras para roteamento, estado, testes e deploy.
Para quem está começando, o caminho mais eficaz é construir. Crie um clone de uma aplicação que você usa diariamente: uma lista de tarefas, um painel de notícias, um formulário de avaliação. Cada projeto solidifica conceitos que tutoriais isolados não conseguem. E quando travar, a documentação oficial e a comunidade são recursos excepcionais.
Perguntas frequentes
+Preciso aprender JavaScript antes de React?
Sim, fortemente recomendado. DOM, eventos, closures, map/filter/reduce e async/await são pré-requisitos. Sem eles, você decora sintaxe sem entender o porquê.
+Class components ou function components?
Function components com hooks são o padrão moderno. Class components ainda funcionam, mas são legado. Novos projetos devem usar functions exclusivamente.
+Qual a diferença entre estado e props?
Props são dados de fora, controlados pelo componente pai. Estado é dados internos, controlados pelo próprio componente. Props são read-only; estado pode ser alterado via setter.
+Por que meu componente renderiza em loop infinito?
Provavelmente você atualiza o estado dentro do corpo do componente (fora de useEffect ou handlers) ou tem um useEffect sem array de dependências que altera estado. Adicione o array correto e mova atualizações para eventos.
+Quando preciso de uma biblioteca de estado global?
Quando múltiplos componentes distantes na árvore precisam compartilhar e modificar os mesmos dados. Para apps pequenos, Context + useState é suficiente. Para médios e grandes, Zustand, Redux Toolkit ou TanStack Query são mais adequados.
Fontes consultadas
Revisão editorial: publicado em . Última revisão em . Conteúdo educativo, sem patrocínio das ferramentas citadas.
Leia também

Como Começar na Programação do Zero em 2026: Guia Definitivo
Roteiro completo para quem quer entrar na programação em 2026: escolha de linguagem, setup de ambiente, lógica de programação, primeiros projetos, comunidades e como evitar armadilhas comuns de iniciantes.

HTML, CSS e JavaScript: O Trio Essencial da Web Moderna
Domine os três pilares do desenvolvimento web: HTML semântico para estrutura, CSS moderno para estilo e layout responsivo, e JavaScript para interatividade, manipulação do DOM e consumo de APIs.

Git e GitHub Básico: Controle de Versão para Quem Coda
Guia prático de Git e GitHub para iniciantes: instalação, commits, branches, merge, rebase, pull requests, resolução de conflitos e fluxos de trabalho profissionais em equipe.