O que é React e a UI declarativa

TL;DR

React é uma biblioteca JavaScript para construir interfaces de usuário declarativas: você descreve o que a tela deve mostrar dado um estado, e o React cuida do como atualizar o DOM. O modelo mental central é UI = f(estado) — a UI é uma função pura do estado da aplicação. O Virtual DOM é a camada intermediária que torna esse modelo eficiente, comparando representações em memória antes de tocar o DOM real. Na era React 19 (2025-2026), o ecossistema amadureceu com Server Components estáveis, Actions, compilador automático e renderização concorrente por padrão.


O problema que o React resolve

Imagine que você precisa construir um carrinho de compras. O usuário adiciona um produto, e você precisa:

  1. Atualizar o contador de itens no header.
  2. Adicionar a linha do produto na lista.
  3. Recalcular o subtotal.
  4. Habilitar o botão “Finalizar” se antes estava desabilitado.
  5. Exibir um badge no ícone do carrinho.

Em JavaScript puro, você escreve cada um desses passos à mão, na ordem certa, toda vez que algo muda. Isso funciona. Por um tempo.

Depois de seis meses e vinte desenvolvedores, você tem um emaranhado de document.getElementById, listeners acumulados e estado espalhado entre variáveis globais. Cada nova feature exige rastrear manualmente quais elementos precisam ser atualizados — e esquecer um deles gera um bug sutil que só aparece em produção.

Esse é o problema central que React veio resolver: como manter a UI sincronizada com o estado da aplicação sem enlouquecer.


Imperativo vs. declarativo: a diferença fundamental

Antes de entrar no React, vale entender essa distinção — ela aparece em entrevistas e explica por que React existe.

Programação imperativa descreve como chegar ao resultado: você dá instruções passo a passo ao computador.

Programação declarativa descreve o que você quer: você descreve o resultado final e delega o como para outra camada.

// ❌ IMPERATIVO — JavaScript puro
// "Faça isso, depois aquilo, depois aquilo..."
const btn = document.getElementById('like-btn') as HTMLButtonElement;
let liked = false;
 
btn.addEventListener('click', () => {
  if (liked) {
    liked = false;
    btn.textContent = 'Curtir';
    btn.classList.remove('active');
  } else {
    liked = true;
    btn.textContent = 'Curtido ✓';
    btn.classList.add('active');
  }
});
// ✅ DECLARATIVO — React
// "Dado este estado, a UI deve parecer assim."
import { useState } from 'react';
 
interface LikeButtonProps {
  initialLiked?: boolean;
}
 
function LikeButton({ initialLiked = false }: LikeButtonProps) {
  const [liked, setLiked] = useState(initialLiked);
 
  return (
    <button
      className={liked ? 'active' : ''}
      onClick={() => setLiked(!liked)}
    >
      {liked ? 'Curtido ✓' : 'Curtir'}
    </button>
  );
}

No código imperativo, você instrui o DOM: “vá nesse elemento, mude esse texto, adicione essa classe”. No código declarativo, você descreve o que o botão deve parecer para cada valor de liked, e o React resolve o resto.


O modelo mental: UI = f(estado)

Essa é a equação central do React. Simples de escrever, profunda de entender:

UI = f(estado)

Leia assim: a interface do usuário é o resultado de aplicar uma função (f) sobre um estado. Cada vez que o estado muda, o React recomputa f(estado) e atualiza a tela para corresponder ao resultado.


flowchart LR
    E1["Estado\n{ liked: false }"] -->|"f(estado)"| V1["UI\n[ Curtir ]"]
    E2["Estado\n{ liked: true }"] -->|"f(estado)"| V2["UI\n[ Curtido ✓ ]"]

    style E1 fill:#4A90D9,color:#fff
    style E2 fill:#4A90D9,color:#fff
    style V1 fill:#E8F4FD,color:#333
    style V2 fill:#27AE60,color:#fff

O que torna isso poderoso é que você nunca mais precisa rastrear transições de estado manualmente. Se o estado é { liked: true }, a UI sempre mostrará o botão ativo — não importa como chegamos a esse estado.

Analogia: planilha eletrônica

Pense numa planilha Excel. Você define fórmulas nas células — quando os dados de entrada mudam, todas as células que dependem deles atualizam automaticamente. Você não instrui “atualize a célula B3 depois de mudar A1”. O modelo declarativo faz o mesmo pela UI.


Componentes: a unidade do React

Se o modelo é UI = f(estado), então componentes são as funções f.

Um componente React é uma função TypeScript que recebe props (dados de entrada) e retorna JSX (uma descrição da UI). Nada mais que isso.

// Um componente é uma função que descreve um pedaço de UI
interface UserCardProps {
  name: string;
  role: string;
  avatarUrl: string;
}
 
function UserCard({ name, role, avatarUrl }: UserCardProps) {
  return (
    <div className="card">
      <img src={avatarUrl} alt={`Avatar de ${name}`} />
      <h2>{name}</h2>
      <p>{role}</p>
    </div>
  );
}
 
// Uso: props entram, UI sai
<UserCard
  name="Ada Lovelace"
  role="Primeira programadora da história"
  avatarUrl="/avatars/ada.jpg"
/>

Componentes são reutilizáveis, composáveis e testáveis de forma independente. Você constrói UIs complexas combinando componentes simples — como montar blocos de Lego.


graph TD
    App["App (raiz)"]
    App --> Header
    App --> Main
    App --> Footer
    Header --> Nav
    Header --> SearchBar
    Main --> ProductList
    ProductList --> ProductCard1["ProductCard (×N)"]
    Main --> Cart
    Cart --> CartItem["CartItem (×N)"]
    Cart --> CheckoutBtn["CheckoutButton"]

    style App fill:#4A90D9,color:#fff
    style ProductCard1 fill:#E8F4FD,color:#333
    style CartItem fill:#E8F4FD,color:#333

Cada caixa no diagrama é uma função. Cada função descreve sua parte da UI. O React compõe tudo isso em uma árvore e renderiza o resultado.


O Virtual DOM: modelo mental

Você já se perguntou: se React recomputa f(estado) cada vez que o estado muda, e o DOM real é lento de atualizar, como isso é eficiente?

A resposta é o Virtual DOM — uma representação leve do DOM real, mantida em memória como um objeto JavaScript.


flowchart LR
    subgraph react["React (em memória)"]
        direction TB
        VDOM_OLD["Virtual DOM\n(antes)"]
        VDOM_NEW["Virtual DOM\n(depois)"]
        DIFF["Diffing\n(o que mudou?)"]
        VDOM_OLD --> DIFF
        VDOM_NEW --> DIFF
    end

    subgraph browser["Browser"]
        DOM["DOM Real"]
    end

    State["Mudança\nde Estado"] --> VDOM_NEW
    DIFF -->|"Patch mínimo"| DOM

    style State fill:#F5A623,color:#fff
    style DIFF fill:#4A90D9,color:#fff
    style DOM fill:#27AE60,color:#fff

O fluxo é:

  1. Estado muda.
  2. React gera um novo Virtual DOM (barato — só um objeto JS).
  3. React compara o novo com o antigo (diffing).
  4. React aplica só as diferenças no DOM real (o patch mínimo).

Isso significa que você pode escrever código como se redesenhasse a UI inteira a cada mudança, mas o React é inteligente o suficiente para tocar apenas o que realmente mudou no DOM.

Virtual DOM não é sobre velocidade bruta

Um equívoco comum: “React é rápido porque Virtual DOM é mais rápido que DOM real”. Isso não é exatamente verdade. DOM manual bem escrito pode ser mais rápido que React. O valor do Virtual DOM é permitir o modelo declarativo com custo razoável — você escreve código simples, e React faz o trabalho tedioso de descobrir o patch mínimo. Para o algoritmo de reconciliation em detalhes, veja 16 - Reconciliation e diffing a fundo (quando existir).


Onde React roda

React não é só “para web”. A biblioteca principal (react) é agnóstica de plataforma — ela manipula uma árvore de componentes. Quem faz o render de fato é um renderer separado:

AmbienteRendererO que renderiza
Browserreact-domDOM HTML
Servidorreact-dom/serverHTML estático (SSR/SSG)
Mobilereact-nativeViews nativas iOS/Android
Desktopreact-native (Electron)Janelas de desktop
PDFs@react-pdf/rendererDocumentos PDF
TerminalinkOutput de CLI
3D@react-three/fiberCenas Three.js

Isso explica por que “aprender React” tem retorno alto: o modelo mental de componentes + estado é transferível para qualquer plataforma.


React 19-era (2025-2026): o que mudou

React 19.0 saiu estável em dezembro de 2024. Em outubro de 2025, chegou o React 19.2. O que mudou em relação ao React 16-18 que você encontra em projetos legados?

Server Components (estáveis)

Antes do React 19, Server Components eram experimentais (disponíveis via Next.js, mas sem suporte oficial estável). Agora são parte canônica da spec.

Server Components rodam apenas no servidor: sem bundle no cliente, sem JavaScript enviado ao browser. São ideais para partes da UI que dependem de dados do banco ou não têm interatividade.

// app/UserProfile.tsx — Server Component (sem 'use client')
// Este componente nunca vai para o bundle do browser
async function UserProfile({ userId }: { userId: string }) {
  const user = await db.users.findById(userId); // acesso direto ao banco!
  return <h1>Olá, {user.name}</h1>;
}

Actions

O pattern antigo para mutações de dados era: chamar uma API no onClick, gerenciar loading manualmente, tratar erros, atualizar o estado local. Actions simplificam isso com primitivas nativas: useActionState, useOptimistic e useFormStatus.

React Compiler

O compilador (anteriormente chamado de React Forget) analisa seu código e adiciona memoização automática onde é seguro fazê-lo. Isso reduz drasticamente a necessidade de useMemo e useCallback escritos à mão — uma fonte histórica de bugs de performance.

Renderização Concorrente por padrão

No React 18, Concurrent Mode era opt-in. No React 19, é o modo padrão. Isso significa que React pode pausar, interromper e retomar trabalho de renderização, mantendo a UI responsiva mesmo durante renders pesados.

Para iniciantes

Você não precisa entender os detalhes internos de concorrência agora. O que importa é saber que React 19 é mais inteligente sobre não travar o browser. Os hooks useTransition e useDeferredValue são as principais APIs que você vai tocar nesse contexto.


Declarativo vs. imperativo: resumo visual


flowchart TD
    subgraph imperativo["Abordagem Imperativa"]
        direction TB
        I1["Evento dispara"]
        I2["Você instrui:\nselecione o elemento"]
        I3["Você instrui:\nmude o texto"]
        I4["Você instrui:\natualize a classe"]
        I5["Você instrui:\nrecalcule o total"]
        I1 --> I2 --> I3 --> I4 --> I5
    end

    subgraph declarativo["Abordagem Declarativa (React)"]
        direction TB
        D1["Estado muda"]
        D2["React recomputa f(estado)"]
        D3["React compara VDOMs"]
        D4["React aplica patch mínimo"]
        D1 --> D2 --> D3 --> D4
    end

    style I1 fill:#F5A623,color:#fff
    style D1 fill:#4A90D9,color:#fff
    style D4 fill:#27AE60,color:#fff

Na abordagem imperativa, você rastreia cada transição. Na abordagem declarativa, você descreve o destino; React traça o caminho.


Armadilhas comuns

Confundir React com um framework completo

O que acontece: Desenvolvedores buscam “como fazer roteamento no React” e ficam confusos ao descobrir que React não tem roteador built-in. Por quê: React é deliberadamente uma biblioteca focada só em UI — não um framework como Angular (que inclui roteamento, HTTP, formulários, DI). Para roteamento, você adiciona React Router ou usa Next.js. Como evitar: Mentalize React como “a camada de UI”. Tudo que não é UI (roteamento, fetch, state global) vem de bibliotecas separadas ou de um meta-framework como Next.js.

Achar que Virtual DOM = performance automática

O que acontece: Desenvolvedores escrevem componentes que re-renderizam desnecessariamente, esperando que o Virtual DOM “resolva” a performance. Por quê: O Virtual DOM reduz operações de DOM real, mas não elimina renders desnecessários do JavaScript. Se um componente pai re-renderiza, todos os filhos re-renderizam por padrão — mesmo que suas props não mudaram. Como evitar: Entender quando usar React.memo, useMemo e useCallback (ou deixar o React Compiler fazer isso por você em projetos novos). Performance é tópico separado.

Tratar o estado como mutável

O que acontece: state.items.push(newItem); setState(state) — o código “funciona” às vezes, falha misteriosamente outras. Por quê: React detecta mudanças de estado comparando referências. Mutar o objeto original não cria uma nova referência, então React pode não detectar que algo mudou e não re-renderizar. Como evitar: Sempre crie novos objetos/arrays: setState([...state.items, newItem]). Estado no React é imutável por convenção.

Pensar em React como "HTML turbinado"

O que acontece: Iniciantes focam em JSX como se fosse HTML com superpoderes e ignoram o modelo mental de estado/componentes. Por quê: JSX parece HTML. Mas JSX é açúcar sintático sobre chamadas de função JavaScript — cada tag JSX é uma chamada a React.createElement(...). A semelhança com HTML é superficial. Como evitar: Leia JSX como “descreve a estrutura”, não “gera HTML diretamente”. O render para HTML é responsabilidade do react-dom, não do JSX em si.


Como explicar em inglês

React is a JavaScript library for building user interfaces using a declarative model. Instead of manually manipulating the DOM, you describe what the UI should look like given a particular state, and React handles the updates efficiently through a virtual DOM diffing algorithm. The core mental model is UI = f(state): the interface is a pure function of your application’s state.

PTEN
UI declarativadeclarative UI
estadostate
componentecomponent
DOM VirtualVirtual DOM
reconciliaçãoreconciliation
renderizaçãorendering
efeito colateralside effect
propriedadesprops
árvore de componentescomponent tree
função purapure function
mutaçãomutation
patch mínimominimal patch / minimal DOM update

O que vem a seguir

Agora que você entende o que React é e por que o modelo declarativo existe, a próxima pergunta natural é: como escrever o código? JSX é a sintaxe que torna possível descrever UI dentro de TypeScript — ela merece uma nota própria.

Depois de JSX, você vai querer entender o ciclo de vida de um componente: quando ele nasce, como recebe dados e quando some da tela.

  • Próximas notas do galho React core (quando existirem) — JSX, Props, State, Hooks e ciclo de vida
  • TypeScript com React — tipagem profunda de componentes, props e hooks
  • JavaScript — fundamento da linguagem sobre a qual React é construído
  • Plataforma Web — o DOM que React abstrai
  • Dicionário de React — termos centrais do ecossistema

Fontes