Estas são as perguntas de entrevista de React que mais aparecem, agrupadas por nível e respondidas do jeito que um entrevistador espera: curtas, corretas para o React 19 e com o motivo por trás da regra. Onde ver o comportamento é melhor do que ler sobre ele, a resposta tem um editor ao vivo, e algumas perguntas pedem que você preveja a saída do console antes de executar.
Antes de clicar: o que o console abaixo da prévia imprime, e o que o botão mostra? A resposta está na seção para iniciantes abaixo.
Perguntas para iniciantes
O que é React?
React é uma biblioteca JavaScript para construir interfaces de usuário a partir de componentes. Você escreve funções que retornam uma descrição da UI para os dados atuais e, quando esses dados mudam, o React descobre o que mudou e atualiza o DOM por você. Ele cuida só da camada de visualização: roteamento, busca de dados e formulários vêm de outras bibliotecas ou de um framework como o Next.js.
O que é JSX?
JSX é uma extensão de sintaxe que permite escrever marcação dentro do JavaScript. Um compilador (Babel, esbuild, SWC) transforma cada tag em uma chamada que cria um elemento React, então <p className="note">{text}</p> vira um objeto com type: 'p' e as props. Como é JavaScript, você usa className em vez de class, coloca expressões em {}, e toda tag precisa ser fechada. A página sobre JSX trata das regras em detalhes.
Qual é a diferença entre um componente e um elemento?
Um componente é uma função (ou classe) que recebe props e retorna UI. Um elemento é o objeto comum que o JSX produz, descrevendo o que renderizar: <Avatar size={40} /> é um elemento cujo type é a função Avatar. O React chama o seu componente para transformar elementos em mais elementos, até chegar às tags do DOM. Elementos são baratos e imutáveis; você nunca chama um componente diretamente.
Qual é a diferença entre props e estado?
Props são passadas pelo pai e são somente leitura dentro do componente. O estado pertence ao componente, muda com o tempo por meio de um setter, e cada mudança agenda uma nova renderização. Um jeito comum de dizer: as props configuram um componente, o estado é a memória dele. O mesmo valor pode ser estado em um pai e prop no filho.
O que o primeiro exemplo desta página registra?
Ele registra logged: 0, e o botão mostra Count: 1, não 2. O estado é uma foto: count é uma constante durante toda a renderização, então as duas chamadas setCount(count + 1) calculam 0 + 1, e o log lê o valor antigo porque o novo só existe na próxima renderização. Para somar dois, use a forma com função de atualização: setCount((c) => c + 1) duas vezes.
Por que listas precisam de keys, e por que o índice é uma key ruim?
O React usa a key para associar cada item da lista ao da renderização anterior. Se você usa o índice do array e insere um item no topo, todos os índices se deslocam, então o React mantém o estado de cada linha na posição antiga e o liga aos dados errados.
Marque Ada e depois clique em "Add to top": a marcação pula para a nova primeira linha. Troque key={index} por key={person.id} e tente de novo, e a marcação fica com Ada. Em desenvolvimento o React também avisa quando faltam keys; a prévia roda como um build de produção, então você não vai ver esse aviso aqui.
O que é um input controlado?
Um input cujo valor vem do estado do React: você passa value e atualiza o estado no onChange, então o React é a única fonte da verdade e você pode validar ou transformar cada tecla. Um input não controlado guarda o próprio valor no DOM, e você o lê quando precisa, por uma ref ou pelo FormData do formulário. Inputs controlados são a escolha padrão quando a UI reage ao que o usuário digita.
O que significa elevar o estado?
Quando dois componentes precisam dos mesmos dados, você move o estado para o pai comum mais próximo deles e o passa para baixo como props, junto com uma função para mudá-lo. Os filhos deixam de ter as próprias cópias, então nunca podem discordar. É a resposta padrão para "como componentes irmãos compartilham estado" antes de recorrer a context ou a uma store.
Quais são as regras dos hooks?
Chame hooks só no nível superior de um componente ou de um hook personalizado, nunca dentro de condições, loops ou funções aninhadas, e só a partir de funções do React, não de funções JavaScript comuns. O React identifica cada hook pela ordem das chamadas, então essa ordem precisa ser idêntica em toda renderização. O pacote eslint-plugin-react-hooks garante as duas regras.
O que é um fragment?
Um fragment agrupa vários elementos sem adicionar um nó ao DOM: <>...</>, ou <Fragment key={id}> quando você precisa de uma key dentro de uma lista. Um componente precisa retornar uma raiz, e os fragments permitem que essa raiz sejam vários irmãos, o que importa dentro de tabelas e layouts flex, em que uma div extra quebraria a marcação.
Perguntas intermediárias
Como funciona o array de dependências do useEffect?
O React executa o efeito depois que a renderização é aplicada (normalmente depois que o navegador pinta a tela) e de novo depois de qualquer renderização posterior em que um valor do array mudou (comparado com Object.is). Sem array ele executa depois de toda renderização; com [] ele executa uma vez depois da primeira. Todo valor do componente que o efeito lê pertence ao array, e o linter avisa quando falta algum.
Quando a limpeza do efeito executa?
A função que você retorna de um efeito executa antes de o efeito executar de novo com novas dependências e uma vez quando o componente desmonta. É ali que você desfaz o que o efeito configurou: limpar um timer, remover um listener, fechar uma conexão.
Clique em "Switch room" e observe o console: a limpeza da sala antiga executa primeiro e depois o efeito conecta à nova. "Hide chat" executa só a limpeza. Em desenvolvimento, o StrictMode adiciona um connect, disconnect, connect extra na montagem para conferir se a sua limpeza funciona; a prévia roda como um build de produção, então você só vê a sequência real.
Por que meu estado parece desatualizado dentro do setInterval?
A callback do interval é uma closure sobre o count da renderização que a criou. Com um array de dependências vazio, o efeito nunca executa de novo, então a callback continua lendo aquele primeiro count para sempre.
broken chega a 1 e para, porque cada tique calcula 0 + 1. fixed continua contando, porque a função de atualização recebe o valor mais recente. Adicionar broken ao array de dependências também funciona, ao custo de limpar e recriar o interval a cada segundo.
O que é batching?
O React agrupa várias atualizações de estado em uma única renderização. Desde o React 18 isso vale em todo lugar: event handlers, timeouts, promises e listeners de eventos nativos. Se você precisa do DOM atualizado logo depois de uma atualização, o flushSync de react-dom desliga o agrupamento, mas raramente você precisa dele.
O clique registra um único render 1 1 1, não três renderizações. Três atualizações de estado dentro de um timeout significavam três renderizações antes do React 18.
O que isto registra? (ordem dos efeitos)
Leia o código e anote as quatro linhas que o console vai imprimir, em ordem, antes de olhar.
A renderização vai de cima para baixo: render App, depois render Child. Os efeitos executam de baixo para cima, depois que a árvore inteira é aplicada: effect Child, depois effect App. O efeito de um pai pode contar com os efeitos dos filhos já terem executado.
Qual é a diferença entre useMemo e useCallback?
useMemo(() => compute(a, b), [a, b]) guarda em cache o resultado de um cálculo. useCallback(fn, [deps]) guarda em cache a própria função, então é o mesmo que useMemo(() => fn, [deps]). Os dois só ajudam quando algo mais adiante compara por referência: um filho com memo ou o array de dependências de outro hook. Desde o React Compiler 1.0 (outubro de 2025), uma etapa de build pode adicionar essa memoização automaticamente, mas a memoização manual continua funcionando e você ainda vai vê-la na maioria dos códigos.
O que o React.memo faz, e por que ele costuma precisar do useCallback?
memo(Component) pula a nova renderização do componente quando as props são as mesmas da última vez, comparadas uma a uma com Object.is. Uma função escrita inline no pai é uma função nova a cada renderização, então conta como uma prop alterada e anula o memo. O useCallback mantém a mesma função entre renderizações.
Limpe o console e clique em "Re-render parent": só aparece render inline handler. O outro filho recebeu a mesma função e foi pulado. Remova o memo(...) em volta de Button e os dois registram a cada clique, o que mostra que o useCallback sozinho não faz nada.
O que é context, e quanto ele custa?
O context passa um valor para todos os componentes abaixo de um provider sem atravessar as props: createContext, depois <ThemeContext value={theme}> no React 19 (ou <ThemeContext.Provider>) e useContext(ThemeContext) para lê-lo. O custo é que todo componente que lê o context renderiza de novo quando o valor muda, e o memo não impede isso. Mantenha-o barato dividindo valores sem relação em contexts separados, envolvendo um valor de objeto em useMemo e deixando estado que muda rápido fora de context de nível do app. Veja useContext.
O que são refs, e quando usar uma em vez de estado?
useRef(initial) retorna um objeto cuja propriedade current persiste entre renderizações, e mudá-la não dispara uma renderização. Use uma ref para valores de que a tela não depende (o id de um timer, o valor anterior, um indicador) e para acesso ao DOM (<input ref={inputRef}> e depois inputRef.current.focus()). Se o valor aparece na tela, ele pertence ao estado.
O que é o virtual DOM, e o que é a reconciliação?
A cada renderização o React monta uma nova árvore de elementos e a compara com a anterior; essa comparação é a reconciliação. Se o tipo de um elemento mudou (uma div virou uma section, ou ProfileA virou ProfileB), o React destrói essa subárvore e o estado dela e monta uma nova. Se o tipo é o mesmo, ele mantém o nó do DOM e atualiza as props que mudaram, e usa as keys para associar os filhos em listas. "Virtual DOM" é o nome popular dessa árvore em memória; a velocidade vem de mexer só no que mudou, não de a árvore em si ser rápida.
O que é um hook personalizado?
Uma função cujo nome começa com use e que chama outros hooks, para que você reutilize lógica com estado entre componentes: useOnlineStatus, useLocalStorage, useDebouncedValue. Cada componente que o chama recebe o próprio estado independente; um hook personalizado compartilha lógica, não dados. Veja hooks personalizados.
O que o StrictMode faz?
<StrictMode> liga verificações extras só em desenvolvimento. Ele renderiza os componentes duas vezes para expor renderizações impuras, executa setup, limpeza e setup dos efeitos uma vez na montagem para expor limpezas faltando, faz o mesmo com as ref callbacks e avisa sobre APIs descontinuadas. Nada disso acontece em um build de produção, então um log duplo no console em desenvolvimento é esperado e não é um bug.
Perguntas avançadas
O que isto registra? (render, layout effect, effect)
Mais uma previsão. Três logs, três momentos diferentes de uma renderização.
A ordem é render, depois useLayoutEffect, depois useEffect, mesmo que o useEffect esteja escrito primeiro. Os layout effects executam depois que o React atualiza o DOM, mas antes de o navegador pintar a tela, e é por isso que servem para medir um elemento; os efeitos normais executam depois, normalmente após a pintura, e devem ser o padrão.
O que é um error boundary?
Um componente de classe que captura erros lançados durante a renderização dos filhos e mostra um fallback em vez de desmontar o app inteiro. Ele precisa de static getDerivedStateFromError (para trocar para o fallback) e normalmente de componentDidCatch (para registrar). Ainda não existe equivalente em hook, então em códigos com componentes de função as equipes escrevem uma classe ou usam o pacote react-error-boundary.
Clique em "Break it": o fallback substitui só os filhos do boundary, o botão fica, e o React ainda reporta o erro capturado no console. Boundaries não capturam erros em event handlers, em código assíncrono como setTimeout nem no próprio boundary. Para esses casos você usa try/catch e define o estado.
O que é um portal?
createPortal(children, domNode) de react-dom renderiza os filhos em outro nó do DOM, normalmente document.body, mantendo-os no mesmo lugar da árvore do React. Modais, tooltips e notificações o usam para escapar do overflow: hidden ou do contexto de empilhamento de um pai. O context continua funcionando através de um portal, e os eventos sobem pela árvore do React, então um clique dentro do portal chega ao onClick do pai mesmo que os nós do DOM estejam em outro lugar. Veja portals.
O que são Suspense e lazy?
lazy(() => import('./Chart')) carrega o código de um componente na primeira vez que ele renderiza, o que divide o seu bundle. <Suspense fallback={<Spinner />}> mostra o fallback enquanto algo dentro dele ainda está carregando: código lazy ou dados lidos com use(promise) ou com um framework que suporte Suspense. Onde você coloca os boundaries decide quais partes da página esperam juntas.
import { lazy, Suspense } from 'react';
const Chart = lazy(() => import('./Chart.jsx'));
export default function Dashboard() {
return (
<Suspense fallback={<p>Loading chart...</p>}>
<Chart />
</Suspense>
);
}
O que o useTransition faz?
Ele marca uma atualização de estado como não urgente. const [isPending, startTransition] = useTransition() e startTransition(() => setTab('posts')) permitem que o React mantenha a tela atual responsiva e interrompa a renderização lenta se chegar uma atualização mais urgente, como uma tecla. isPending indica quando mostrar uma dica. No React 19 a função que você passa pode ser assíncrona, e é isso que o React chama de action. Não o use para atualizar o próprio valor de um input de texto; essa atualização precisa ser urgente.
O que são React Server Components?
Componentes que executam só no servidor (ou no momento do build) e enviam ao navegador o resultado renderizado, nunca o código. Eles podem ser async e ler um banco de dados ou o sistema de arquivos diretamente, mas não podem usar estado, efeitos nem APIs do navegador. Um arquivo marcado com 'use client' inicia uma fronteira de cliente onde moram os componentes interativos, e 'use server' marca server functions que o código do cliente pode chamar. Você os usa por meio de um framework como o Next.js com o App Router; apps Vite comuns não têm um servidor para executá-los.
O que mudou no React 19?
- Actions: funções assíncronas em transições, com o estado pendente tratado por você. Um
<form action={fn}>chamafncom oFormDatado formulário. - Novos hooks:
useActionStatepara o resultado e o estado pendente de um formulário,useOptimisticpara UI otimista euseFormStatusemreact-dom. use: lê uma promise (suspendendo até ela resolver) ou um context e, ao contrário dos outros hooks, pode ser chamado dentro de uma condição.refcomo prop: componentes de função recebemrefcomo qualquer outra prop, então oforwardRefnão é mais necessário em código novo. Ref callbacks podem retornar uma função de limpeza.<Context>como provider, além de tags<title>e<meta>que sobem para o head do documento.- Remoções:
ReactDOM.render, string refs, context legado edefaultPropsem componentes de função (use parâmetros com valor padrão).
// React 19: ref is a normal prop
function TextInput({ ref, ...props }) {
return <input ref={ref} {...props} />;
}
A página do React 19 tem exemplos executáveis de cada um.
Como você testa componentes React?
Com React Testing Library e um runner como Vitest ou Jest. Você renderiza o componente, encontra os elementos do jeito que um usuário faria (por papel, rótulo ou texto), interage com user-event e verifica o que está visível, não o estado interno. Isso mantém os testes válidos através de refatorações.
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Counter from './Counter';
test('counts clicks', async () => {
const user = userEvent.setup();
render(<Counter />);
await user.click(screen.getByRole('button', { name: /clicked 0 times/i }));
expect(screen.getByRole('button')).toHaveTextContent('Clicked 1 times');
});
toHaveTextContent vem de @testing-library/jest-dom. Para fluxos completos entre páginas, as equipes adicionam Playwright ou Cypress por cima.
Como você encontra e corrige um problema de performance?
Meça primeiro. Abra a aba Profiler do React DevTools, grave a interação lenta e leia o flame chart: ele mostra quais componentes renderizaram, quanto tempo cada um levou e (com a configuração "record why each component rendered") por quê. Correções típicas, na ordem em que vale tentar: mover o estado para baixo para que menos componentes dependam dele, passar subárvores lentas como children, memoizar a parte cara com memo, useMemo e useCallback, virtualizar listas longas e adiar atualizações pesadas com useTransition ou useDeferredValue. Faça o profiling em um build de produção ou de profiling; builds de desenvolvimento são mais lentos e exageram os tempos de renderização.
Por que um componente deve ser puro?
Dados as mesmas props, o mesmo estado e o mesmo context, um componente deve retornar o mesmo JSX e não mudar nada fora de si enquanto renderiza. O React pode renderizar um componente mais de uma vez, fora de ordem, ou descartar uma renderização (transições, Suspense, StrictMode), então efeitos colaterais no corpo, como mutar uma variável ou enviar uma requisição, executam um número imprevisível de vezes. Efeitos colaterais ficam primeiro em event handlers, e em efeitos quando nenhum evento os causou.
Quando você não deve usar um efeito?
Quando o valor pode ser calculado durante a renderização (listas filtradas, nomes completos, totais), quando o trabalho é causado por uma ação do usuário (coloque-o no event handler) e quando você quer reiniciar o estado quando uma prop muda (use uma key). Efeitos servem para sincronizar com algo fora do React: uma conexão de rede, uma API do navegador, um widget de terceiros. Cadeias de efeitos que definem estado são uma fonte comum de renderizações extras e de bugs.
Perguntas frequentes
O que é React?
React é uma biblioteca JavaScript para construir interfaces de usuário a partir de componentes. Você descreve como a tela deve ficar para os dados atuais, e o React atualiza o DOM real quando esses dados mudam.
Qual é a diferença entre estado e props?
Props são entradas que um pai passa para um componente, e o componente as trata como somente leitura. Estado são dados que um componente possui e muda com o tempo por meio de um setter, o que faz o React renderizá-lo de novo.
O que são hooks no React?
Hooks são funções cujos nomes começam com use e que permitem a um componente de função usar recursos do React: useState para estado, useEffect para efeitos colaterais, useContext para context, useRef para valores que não disparam renderizações, e outros.
O que é o virtual DOM?
É o nome da descrição em memória que o React faz da UI. A cada renderização o React monta uma nova descrição, compara-a com a anterior e aplica só as diferenças ao DOM real. Essa comparação se chama reconciliação.
Por que as keys importam em listas no React?
Uma key diz ao React qual item de uma lista é qual entre renderizações. Com keys estáveis (como um id), o React mantém o estado e o nó DOM de cada item ligados aos dados certos quando itens são adicionados, removidos ou reordenados. Usar o índice do array quebra isso quando a ordem muda.
O que é JSX?
JSX é uma extensão de sintaxe que permite escrever marcação parecida com HTML em JavaScript. Um compilador transforma cada tag em uma chamada de função que cria um elemento React, então <h1>Hi</h1> vira um objeto comum que descreve um h1.