Modelos mentais do React deixam o React simples: aprenda as ideias-chave sobre componentes, render, estado e efeitos, e aplique-as para construir UI rapidamente via chat.

O React pode ser frustrante no começo porque você vê a UI mudar, mas nem sempre consegue explicar por que mudou. Você clica em um botão, algo atualiza e então outra parte da página te surpreende. Normalmente não é “o React é estranho”. É “a minha imagem do que o React está fazendo está borrada”.
Um modelo mental é a história simples que você conta para si mesmo sobre como algo funciona. Se a história estiver errada, você tomará decisões confiantes que levam a resultados confusos. Pense em um termostato: um modelo ruim é “eu ajusto para 22°C, então o quarto vira 22°C instantaneamente.” Um modelo melhor é “eu ajusto um alvo, e o aquecedor liga e desliga ao longo do tempo para alcançá-lo.” Com a história melhor, o comportamento deixa de parecer aleatório.
O React funciona do mesmo jeito. Depois de adotar algumas ideias claras, o React se torna previsível: você pode olhar os dados atuais e adivinhar de forma confiável o que estará na tela.
Dan Abramov ajudou a popularizar essa mentalidade de “tornar previsível”. O objetivo não é memorizar regras. É manter um pequeno conjunto de verdades na cabeça para que você debuge raciocinando, não por tentativa e erro.
Mantenha estas ideias em mente:
Segure isso e o React deixa de parecer mágica. Passa a ser um sistema em que você pode confiar.
O React fica mais fácil quando você para de pensar em “telas” e começa a pensar em pedaços pequenos. Um componente é uma unidade reutilizável de UI. Ele recebe entradas e retorna uma descrição de como a UI deve ficar para aquelas entradas.
Ajuda tratar um componente como uma descrição pura: “dado estes dados, mostre isso.” Essa descrição pode ser usada em muitos lugares porque não depende de onde o componente vive.
Props são as entradas. Elas vêm de um componente pai. Props não são “posse” do componente, e não é algo que o componente deva mudar silenciosamente. Se um botão recebe label="Save", o trabalho do botão é renderizar esse label, não decidir que ele deveria ser diferente.
State é dado possuído. É o que o componente lembra ao longo do tempo. O state muda quando o usuário interage, quando uma requisição termina ou quando você decide que algo deve ser diferente. Ao contrário das props, o state pertence àquele componente (ou ao componente que você escolher para ser o dono).
Versão direta da ideia chave: a UI é uma função do state. Se o state diz “loading”, mostre um spinner. Se o state diz “error”, mostre uma mensagem. Se o state diz “items = 3”, renderize três linhas. Seu trabalho é manter a UI lendo do state, não derivando para variáveis escondidas.
Uma forma rápida de separar os conceitos:
SearchBox, ProfileCard, CheckoutForm)name, price, disabled)isOpen, query, selectedId)Exemplo: um modal. O pai pode passar title e onClose como props. O modal pode possuir isAnimating como state.
Mesmo se você estiver gerando UI por chat (por exemplo no Koder.ai), essa separação ainda é a forma mais rápida de não perder a cabeça: decida o que é props vs state primeiro, depois deixe a UI seguir.
Uma forma útil de manter o React na cabeça (muito no espírito do Dan Abramov) é: renderizar é um cálculo, não um trabalho de pintura. O React executa suas funções de componente para descobrir como a UI deve ficar com os props e state atuais. A saída é uma descrição da UI, não pixels.
Um re-render só significa que o React repete aquele cálculo. Não quer dizer “a página inteira é redesenhada.” O React compara o novo resultado com o anterior e aplica o menor conjunto de mudanças no DOM real. Muitos componentes podem re-renderizar enquanto apenas alguns nós do DOM realmente mudam.
A maioria dos re-renders acontece por alguns motivos simples: o state de um componente mudou, suas props mudaram, ou um pai re-renderizou e o React pediu ao filho para renderizar novamente. Esse último surpreende as pessoas, mas normalmente tudo bem. Se você tratar render como “barato e monótono”, seu app continua mais fácil de entender.
A regra prática que mantém isso limpo: torne o render puro. Dadas as mesmas entradas (props + state), seu componente deve retornar a mesma descrição da UI. Mantenha surpresas fora do render.
Exemplo concreto: se você gerar um ID com Math.random() dentro do render, um re-render vai mudá-lo e de repente uma checkbox perde foco ou um item da lista remonta. Crie o ID uma vez (state, memo, ou fora do componente) e o render fica estável.
Se lembrar de uma frase: um re-render significa “recalcular como a UI deve ser”, não “reconstruir tudo”.
Outro modelo útil: atualizações de state são pedidos, não atribuições instantâneas. Quando você chama um setter como setCount(count + 1), você está pedindo ao React para agendar um render com um novo valor. Se você ler o state logo em seguida, pode ainda ver o valor antigo porque o React ainda não fez o render.
Por isso importam atualizações “pequenas e previsíveis”. Prefira descrever a mudança em vez de pegar o que você acha que é o valor atual. Quando o próximo valor depende do anterior, use a forma updater: setCount(c => c + 1). Isso bate com o modo como o React funciona: várias atualizações podem ser enfileiradas e então aplicadas em ordem.
Imutabilidade é a outra metade da imagem. Não altere objetos e arrays no lugar. Crie um novo com a mudança. Assim o React pode ver “este valor é novo” e seu cérebro consegue rastrear o que mudou.
Exemplo: alternar um todo. A abordagem segura é criar um novo array e um novo objeto todo para o item que você mudou. A abordagem arriscada é trocar todo.done = !todo.done dentro do array existente.
Também mantenha o state mínimo. Uma armadilha comum é armazenar valores que você pode calcular. Se você já tem items e filter, não guarde filteredItems no state. Calcule durante o render. Menos variáveis de state significam menos formas de os valores saírem de sincronia.
Um teste simples para o que pertence ao state:
Se você está construindo UI via chat (incluindo no Koder.ai), peça mudanças como patches pequenos: “Adicione uma flag booleana” ou “Atualize esta lista imutavelmente.” Mudanças pequenas e explícitas mantêm o gerador e seu código React alinhados.
Renderizar descreve a UI. Efeitos sincronizam com o mundo exterior. “Externo” significa coisas que o React não controla: chamadas de rede, timers, APIs do navegador e às vezes trabalho imperativo no DOM.
Se algo pode ser calculado a partir de props e state, normalmente não deveria viver em um efeito. Colocar isso em um efeito adiciona um segundo passo (render, rodar efeito, set state, render de novo). Esse salto extra é onde aparecem piscadas, loops e bugs do tipo “por que isso está obsoleto?”.
Uma confusão comum: você tem firstName e lastName, e guarda fullName no state usando um efeito. Mas fullName não é um efeito colateral. É dado derivado. Calcule durante o render e ele sempre vai bater.
Como hábito: derive valores de UI durante o render (ou com useMemo quando algo for realmente custoso), e use efeitos para “fazer algo” externo, não para “descobrir algo”.
Trate o array de dependências como: “Quando esses valores mudarem, re-sincronize com o mundo exterior.” Não é um truque de performance e não é um lugar para silenciar avisos.
Exemplo: se você busca detalhes do usuário quando userId muda, userId pertence ao array de dependências porque deve disparar a sincronização. Se o efeito usa token também, inclua-o, ou você pode buscar com um token antigo.
Um bom teste intuitivo: se remover um efeito só deixaria a UI errada, provavelmente não era um efeito real. Se removê-lo pararia um timer, cancelaria uma assinatura ou impediria um fetch, então provavelmente era um efeito.
Um bom modelo inicial é: UI = f(state, props). Seus componentes não “editam o DOM”; eles descrevem o que deve estar na tela para os dados atuais. Se a tela estiver errada, inspecione o state/props que a gerou, não o DOM.
Props são entradas de um pai; seu componente deve tratá-las como somente leitura. State é memória pertencente a um componente (ou ao componente que você escolheu como dono). Se um valor precisa ser compartilhado, eleve-o e passe-o como props.
Um re-render significa que o React re-executa sua função de componente para calcular a próxima descrição da UI. Não quer dizer que a página inteira foi repintada automaticamente. O React então atualiza o DOM real com o menor conjunto de mudanças necessário.
Porque as atualizações de state são agendadas, não atribuições imediatas. Se o próximo valor depende do anterior, use a forma updater para não depender de um valor possivelmente obsoleto:
setCount(c => c + 1)Isso continua correto mesmo se várias atualizações estiverem na fila.
Evite armazenar qualquer coisa que você possa calcular a partir das entradas existentes. Armazene as entradas e derive o resto durante o render.
Exemplos:
items, filtervisibleItems = items.filter(...)Isso evita que valores fiquem fora de sincronia.
Use efeitos para sincronizar com coisas que o React não controla: fetch, assinaturas, timers, APIs do browser ou trabalho imperativo no DOM.
Não use um efeito apenas para calcular valores da UI a partir do state—calcule isso durante o render (ou com useMemo se for caro).
Trate as dependências como uma lista de gatilho: “quando esses valores mudarem, re-sincronize”. Inclua todo valor reativo que o efeito lê.
Se deixar algo de fora, você corre o risco de dados obsoletos (como um userId ou token antigo). Se acrescentar coisas erradas, pode criar loops—frequentemente sinal de que o trabalho do efeito pertence a handlers ou ao render.
Se duas partes da UI precisam sempre concordar, coloque o state no pai comum mais próximo, passe o valor para baixo e passe callbacks para cima.
Um teste rápido: se você está duplicando o mesmo valor em dois componentes e escrevendo efeitos para “mantê-los sincronizados”, provavelmente esse state precisa de um dono único.
Geralmente acontece quando um handler “captura” um valor antigo de uma renderização anterior. Correções comuns:
setX(prev => ...)Se um clique usa “o valor de ontem”, suspeite de um fechamento obsoleto.
Comece com um pequeno plano: componentes, donos do state e eventos. Gere código como pequenos patches (adicione um campo de state, adicione um handler, derive um valor) em vez de reescritas grandes.
Se usar um construtor por chat como Koder.ai, peça:
Isso mantém o código gerado alinhado com o modelo mental do React.