Erros Comuns em JSX e Como Evitá-los
JSX parece enganosamente simples—é apenas HTML em JavaScript, certo? No entanto, até desenvolvedores experientes tropeçam em suas peculiaridades, especialmente à medida que o React evolui. Com o runtime JSX automático do React 19, Server Components e o cenário em constante mudança dos frameworks modernos, esses erros têm novas implicações. Aqui está o que ainda atrapalha os desenvolvedores e como evitar essas armadilhas.
Pontos-Chave
- Índices de arrays como keys causam problemas de reconciliação e quebram os recursos concorrentes do React
- Server Components requerem padrões diferentes dos client components, especialmente em relação às APIs do navegador
- O runtime JSX automático muda como seu código é transformado e requer configuração adequada
- Funções inline e padrões de renderização condicional podem degradar silenciosamente o desempenho
A Evolução do JSX: Por Que Velhos Hábitos Quebram Código Novo
O runtime JSX automático introduzido no React 17 eliminou a necessidade de importar React em cada arquivo, mas também criou nova confusão. Seu JSX agora se transforma de forma diferente—funções jsx substituem React.createElement, e ferramentas de build mal configuradas podem quebrar silenciosamente sua aplicação.
Em Server Components, os riscos são maiores. JSX que funciona perfeitamente no client-side trava quando tenta acessar window ou usa hooks no contexto errado. As regras não apenas mudaram; elas se multiplicaram.
Armadilhas Críticas de JSX no React Moderno
1. Keys Instáveis Que Destroem o Desempenho
// ❌ Índice como key - causa problemas de reconciliação
items.map((item, index) => <Item key={index} {...item} />)
// ✅ Identificador estável e único
items.map(item => <Item key={item.id} {...item} />)
Usar índices de arrays como keys permanece um dos erros de JSX mais prejudiciais. Nos recursos concorrentes do React, keys instáveis não apenas causam oscilações—elas podem quebrar boundaries do Suspense e disparar re-renderizações desnecessárias em toda a sua árvore de componentes.
2. Renderização Direta de Objetos
// ❌ Objetos não são children válidos do React
const user = { name: 'Alice', age: 30 };
return <div>{user}</div>;
// ✅ Renderize propriedades específicas
return <div>{user.name}</div>;
Esta mensagem de erro não mudou desde o React 15, mas desenvolvedores ainda tentam renderizar objetos diretamente. Com a inferência JSX do TypeScript, você detectará isso em tempo de compilação—se seu tsconfig.json estiver configurado adequadamente.
3. Funções Inline Criando Novas Referências
// ❌ Nova função a cada renderização
<Button onClick={() => handleClick(id)} />
// ✅ Referência estável com useCallback
const handleButtonClick = useCallback(() => handleClick(id), [id]);
<Button onClick={handleButtonClick} />
No pipeline de renderização do React, funções inline não apenas causam problemas de desempenho—elas quebram a otimização do memo e podem disparar atualizações em cascata por toda a sua árvore de componentes.
Discover how at OpenReplay.com.
Server Components: Onde as Regras do JSX Mudam
4. Código Client-Only em Server Components
// ❌ Trava em Server Components
export default function ServerComponent() {
const width = window.innerWidth; // ReferenceError
return <div style={{ width }} />;
}
// ✅ Use a diretiva client ou passe do cliente
'use client';
import { useState, useEffect } from 'react';
export default function ClientComponent() {
const [width, setWidth] = useState(0);
useEffect(() => {
setWidth(window.innerWidth);
}, []);
return <div style={{ width }} />;
}
Server Components executam fora do navegador onde APIs do DOM não existem. Isso não é um problema de configuração—é arquitetural.
5. Componentes Assíncronos Sem Suspense
// ❌ Promise não tratada em Server Component
async function UserProfile({ id }) {
const user = await fetchUser(id);
return <div>{user.name}</div>;
}
// ✅ Envolva com boundary do Suspense
<Suspense fallback={<Loading />}>
<UserProfile id={userId} />
</Suspense>
React Server Components podem ser assíncronos, mas sem boundaries adequados do Suspense, eles bloquearão a renderização ou travarão com erros enigmáticos.
Armadilhas Modernas de Configuração JSX
6. Configuração de Runtime JSX Incompatível
// ❌ Transform antigo no tsconfig.json
{
"compilerOptions": {
"jsx": "react" // Requer importações do React
}
}
// ✅ Runtime automático para React 17+
{
"compilerOptions": {
"jsx": "react-jsx" // Não precisa importar React
}
}
O runtime JSX automático não é apenas uma conveniência—é necessário para tamanho de bundle otimizado e compatibilidade com Server Components. Configuração incorreta aqui causa falhas silenciosas que só aparecem em produção.
7. Anti-Padrões de Renderização Condicional
// ❌ Retorna 0 em vez de nada
{count && <Counter value={count} />}
// ✅ Conversão explícita para booleano
{Boolean(count) && <Counter value={count} />}
Quando count é 0, JSX renderiza o número 0, não nada. Este erro é particularmente visível no React Native onde nós de texto requerem containers adequados.
Estratégias de Prevenção
Configure Suas Ferramentas Adequadamente: Configure o ESLint com eslint-plugin-react e habilite estas regras:
react/jsx-keyreact/jsx-no-bindreact/display-name
Use TypeScript: Com configuração JSX adequada, TypeScript detecta a maioria desses erros em tempo de compilação. Habilite o modo strict e configure jsx adequadamente no seu tsconfig.json.
Entenda Seu Runtime: Saiba se seu componente executa no servidor ou no cliente. Next.js 14+ torna isso explícito com a diretiva 'use client', mas o modelo mental se aplica em todos os lugares.
Conclusão
Erros de JSX em 2024 não são apenas sobre sintaxe—são sobre entender onde e como seu código executa. O runtime JSX automático mudou o modelo de transformação. Server Components mudaram o modelo de execução. Os recursos concorrentes do React mudaram o modelo de desempenho.
Domine esses fundamentos, e você escreverá JSX que não é apenas correto, mas otimizado para as capacidades do React moderno. O melhor JSX é invisível—ele sai do caminho e deixa seus componentes brilharem.
Perguntas Frequentes
Quando você usa índices de arrays como keys, o React não consegue rastrear adequadamente quais itens mudaram, foram movidos ou removidos. Isso força o React a re-renderizar mais componentes do que o necessário e pode fazer com que o estado seja associado ao componente errado após reordenação.
Embora funções inline funcionem funcionalmente, elas criam novas referências a cada renderização, quebrando otimizações do React.memo e potencialmente causando re-renderizações desnecessárias de componentes filhos. Para melhor manutenibilidade, use useCallback para event handlers que dependem de props ou state.
A configuração react usa a transformação clássica React.createElement que requer importações do React em cada arquivo. A configuração react-jsx usa o runtime automático introduzido no React 17, que lida com a transformação sem importações explícitas do React e produz bundles menores.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.