icardb
React para Iniciantes: Componentes, Estado e o Fluxo de Dados
Voltar para artigosPROGRAMAÇÃO

React para Iniciantes: Componentes, Estado e o Fluxo de Dados

Por Equipe Editorial Icardb 7 min de leitura

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.

bash
# 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 dev

A 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.

tsx
// 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.

tsx
// 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.

tsx
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.

tsx
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.

tsx
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.

tsx
// 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.

HookUso principalQuando usar
useRefReferência mutável persistente entre rendersAcesso a elementos DOM, timers, flags de controle
useMemoMemorização de valores computadosCálculos caros que não precisam refazer a cada render
useCallbackMemorização de funçõesEvitar recriação de callbacks passados a componentes filhos otimizados
useContextAcesso a valores globais sem prop drillingTemas, autenticação, preferências de usuário
useReducerEstado complexo com lógica de transiçãoFormulários multi-campo, máquinas de estado, lógica condensada
tsx
// 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.

Crédito da imagem: Foto: Icardb / Gerado por IA (Uso Editorial)

Leia também