JSX e TSX
Escreva UI declarativa usando expressões JavaScript que se parecem com HTML - com suporte completo a TypeScript.
Busque em todas as páginas da documentação
Escreva UI declarativa usando expressões JavaScript que se parecem com HTML - com suporte completo a TypeScript.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Cartão de receita de referência rápida - pronto para copiar e colar.
// Expressão JSX
const element = <h1 className="title">Olá, {name}</h1>
// Fragment (sem nó DOM extra)
const list = (
<>
<dt>Termo</dt>
<dd>Definição</dd>
</>
)
// Espaço para expressão - qualquer expressão JS válida funciona dentro de { }
<p>{isLoggedIn ? `Bem-vindo, ${user.name}` : "Por favor, faça login"}</p>
// Espalhar props
<Button {...props} />Quando usar isso: Todo componente React retorna JSX. Entender as regras economiza horas de depuração.
"use client";
import { useState } from "react";
interface UserCardProps {
name: string;
role: "admin" | "editor" | "viewer";
avatarUrl?: string;
}
export function UserCard({ name, role, avatarUrl }: UserCardProps) {
const [expanded, setExpanded] = useState(false);
const roleBadge: Record<string, string> = {
admin: "bg-red-100 text-red-800",
editor: "bg-blue-100 text-blue-800",
viewer: "bg-gray-100 text-gray-800",
};
return (
<article className="rounded-lg border p-4">
<div className="flex items-center gap-3">
{avatarUrl ? (
<img
src={avatarUrl}
alt={`Avatar de ${name}`}
className="h-10 w-10 rounded-full"
/>
) : (
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-gray-200">
{name[0]}
</div>
)}
<div>
<h2 className="font-semibold">{name}</h2>
<span className={`rounded px-2 py-0.5 text-xs ${roleBadge[role]}`}>
{role}
</span>
</div>
</div>
{expanded && (
<p className="mt-3 text-sm text-gray-600">
{name} tem permissões de <strong>{role}</strong> neste workspace.
</p>
)}
<button
onClick={() => setExpanded(prev => !prev)}
className="mt-2 text-sm text-blue-600 underline"
>
{expanded ? "Mostrar menos" : "Mostrar mais"}
</button>
</article>
);
}O que isso demonstra:
className dinâmico usando template literals<div className="x"> compila para React.createElement("div", { className: "x" }) (ou o transformador JSX moderno que importa jsx de react/jsx-runtime automaticamente)<>...</> (Fragment) quando não quiser um wrapper extra no DOM{ } criam um espaço para expressão - tudo que produz um valor funciona: variáveis, ternários, chamadas de função, métodos de array.tsx e suporta verificação de tipo TypeScript para props, expressões e manipuladores de eventos| Regra | Correto | Incorreto |
|---|---|---|
class do HTML | className | class |
for do HTML | htmlFor | for |
| Tags de auto-fechamento | <img /> | <img> |
Prop style | style={{ color: "red" }} | style="color:red" |
| Atributos booleanos | <input disabled /> | <input disabled="true"> |
Atributos data | data-testid="x" | Funciona como está |
// Fragment nomeado (quando você precisa de uma chave)
import { Fragment } from "react";
{items.map(item => (
<Fragment key={item.id}>
<dt>{item.term}</dt>
<dd>{item.definition}</dd>
</Fragment>
))}
// Sintaxe curta (sem chave necessária)
<>
<Header />
<Main />
<Footer />
</>// React.ReactNode - o tipo mais amplo
function Wrapper({ children }: { children: React.ReactNode }) {
return <section>{children}</section>;
}
// React.JSX.Element - um único elemento JSX
function Badge(): React.JSX.Element {
return <span>OK</span>;
}
// Componentes genéricos
function List<T>({ items, render }: { items: T[]; render: (item: T) => React.ReactNode }) {
return <ul>{items.map((item, i) => <li key={i}>{render(item)}</li>)}</ul>;
}class vs className - Usar class em JSX compila, mas dispara um aviso no console e não aplica estilos corretamente em alguns ambientes. Correção: Sempre use className.
Elementos adjacentes sem um wrapper - Retornar <h1/><p/> sem um elemento pai é um erro de sintaxe. Correção: Envolva em um Fragment <>...</> ou em uma <div>.
Renderizar objetos - {user} lança "Objects are not valid as a React child" se user for um objeto. Correção: Renderize uma propriedade específica como {user.name}.
Colapso de espaços em branco - JSX colapsa espaços em branco de forma mais agressiva que o HTML. Dois elementos inline como <span>A</span><span>B</span> não terão espaço entre eles. Correção: Adicione {" "} entre eles ou envolva com CSS gap.
Comentários em JSX - Comentários HTML <!-- --> não funcionam. Correção: Use {/* comentário */} dentro do JSX.
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| Template literals (tagged) | Construir HTML de e-mail ou strings estáticas no lado do servidor | Você precisa de interatividade ou recursos do React |
React.createElement | Construir elementos programaticamente em um loop sem JSX | A legibilidade importa (JSX é quase sempre mais claro) |
| MDX | Escrever páginas ricas em conteúdo que misturam Markdown e componentes | Construir UI de aplicativos interativos |
TSX é JSX dentro de arquivos .tsx com verificação de tipo TypeScript habilitada. A sintaxe é idêntica, mas TSX valida tipos de props, tipos de expressões e tipos de manipuladores de eventos em tempo de compilação.
class é uma palavra-chave reservada em JavaScript. JSX compila para chamadas de função JavaScript, então o React usa className para evitar o conflito. Usar class dispara um aviso no console.
Qualquer expressão JavaScript válida - variáveis, ternários, chamadas de função, template literals e métodos de array como .map(). Instruções como if/else ou loops for não podem ir diretamente dentro de {}.
Use <>...</> quando precisar retornar múltiplos elementos irmãos sem adicionar um nó DOM extra. Use <Fragment key={...}> ao mapear uma lista que precisa de chaves no wrapper.
A prop style aceita um objeto JavaScript com propriedades camelCase, não uma string CSS:
<div style={{ backgroundColor: "red", fontSize: 16 }} />Não diretamente. Use uma expressão ternária {condicao ? <A /> : <B />} ou extraia a lógica para uma variável antes da instrução return.
<Button {...props} /> passa todas as propriedades do objeto props como atributos individuais para o componente. Isso é útil para encaminhar props ou estender elementos HTML nativos.
Use {/* comentário */} dentro do JSX. Comentários no estilo HTML <!-- --> não funcionam e causarão um erro de sintaxe.
React.ReactNode é o tipo mais amplo - inclui JSX, strings, números, null, undefined e arraysReact.JSX.Element é apenas um único elemento JSX, sem strings ou nullReactNode para props de children e JSX.Element para tipos de retorno de função que sempre retornam JSXExpressões JSX compilam para uma única chamada de função como React.createElement(...). Múltiplos elementos adjacentes seriam múltiplos valores de retorno, o que o JavaScript não suporta. Envolva irmãos em um Fragment ou em um elemento contêiner.
Use dangerouslySetInnerHTML={{ __html: htmlString }}. Use isso apenas com conteúdo sanitizado e confiável - ele contorna as proteções XSS do React.
Eles não renderizam nada. É por isso que {condicao && <Component />} funciona - quando condicao é false, false renderiza como vazio. No entanto, 0 renderiza como o texto "0".
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥