kb.erickguedes.com
React: Construindo Interfaces Modernas

Fundamentos do JSX e Componentes

Aula 1 de 8

O que é JSX?

JSX é uma extensão de sintaxe para JavaScript que parece HTML, mas é compilada para chamadas de React.createElement.

// JSX — parece HTML, mas é JavaScript
const elemento = <h1>Olá, mundo!</h1>;

// Compilado para:
const elemento = React.createElement("h1", null, "Olá, mundo!");

Expressões em JSX

const nome = "Alice";
const idade = 30;

const elemento = (
  <div>
    <h1>Olá, {nome}!</h1>
    <p>Você tem {idade} anos.</p>
    <p>Ano que vem: {idade + 1}</p>
    {nome.toUpperCase()}
  </div>
);

Atributos em JSX

// className em vez de class
const elemento = <div className="container">Conteúdo</div>;

// Atributos dinâmicos
const url = "https://exemplo.com";
const label = "Saiba mais";
const link = <a href={url}>{label}</a>;

// Style com objeto (camelCase)
const estilo = {
  backgroundColor: "blue",
  color: "white",
  padding: "1rem",
};
const botao = <button style={estilo}>Clique</button>;

Conditional Rendering

function Saudacao({ nome }: { nome?: string }) {
  // Ternário
  return (
    <div>
      {nome ? (
        <h1>Olá, {nome}!</h1>
      ) : (
        <h1>Olá, visitante!</h1>
      )}

      {/* AND lógico */}
      {nome && <p>Bem-vindo de volta!</p>}

      {/* OR lógico */}
      {nome || <p>Faça login para continuar.</p>}
    </div>
  );
}

Componentes Function Component

// Componente simples
function Saudacao({ nome }: { nome: string }) {
  return <h1>Olá, {nome}!</h1>;
}

// Arrow function
const Saudacao = ({ nome }: { nome: string }) => {
  return <h1>Olá, {nome}!</h1>;
};

// Uso
function App() {
  return (
    <div>
      <Saudacao nome="Alice" />
      <Saudacao nome="Bob" />
    </div>
  );
}

Props e Tipagem

interface CardProps {
  titulo: string;
  descricao: string;
  imagem?: string;
  onClick?: () => void;
}

function Card({ titulo, descricao, imagem, onClick }: CardProps) {
  return (
    <div className="card" onClick={onClick}>
      {imagem && <img src={imagem} alt={titulo} />}
      <h2>{titulo}</h2>
      <p>{descricao}</p>
    </div>
  );
}

children (Composição)

interface ContainerProps {
  children: React.ReactNode;
  className?: string;
}

function Container({ children, className }: ContainerProps) {
  return (
    <div className={`container ${className ?? ""}`}>
      {children}
    </div>
  );
}

function App() {
  return (
    <Container className="main">
      <h1>Título</h1>
      <p>Conteúdo aninhado.</p>
    </Container>
  );
}

Fragment

function Lista() {
  return (
    <>
      <h1>Itens</h1>
      <ul>
        <li>Item 1</li>
        <li>Item 2</li>
      </ul>
    </>
  );
}

// Ou explicitamente:
import { Fragment } from "react";

function Lista() {
  return (
    <Fragment>
      <h1>Itens</h1>
      <ul>
        <li>Item 1</li>
      </ul>
    </Fragment>
  );
}

Renderização de Listas

interface Item {
  id: number;
  texto: string;
}

function ListaItens({ items }: { items: Item[] }) {
  return (
    <ul>
      {items.map((item) => (
        <li key={item.id}>{item.texto}</li>
      ))}
    </ul>
  );
}

// key — identificador único
// Use ID estável, nunca o índice (a menos que a lista seja estática)

React.createElement e Virtual DOM

// JSX é açúcar sintático para:
React.createElement(
  "div",
  { className: "container" },
  React.createElement("h1", null, "Título"),
  React.createElement("p", null, "Parágrafo"),
);

// O Virtual DOM é uma representação JS leve do DOM real
// React compara (diff) o VDOM anterior com o novo
// Aplica apenas as mudanças necessárias no DOM real (reconciliation)
Virtual DOM:
  ├── Render: React cria nova árvore VDOM
  ├── Diff: Compara com a anterior
  └── Patch: Aplica só as diferenças no DOM real

Lab: Primeiro Componente

interface TaskItemProps {
  id: number;
  titulo: string;
  concluida: boolean;
}

function TaskItem({ id, titulo, concluida }: TaskItemProps) {
  return (
    <div style={{
      display: "flex",
      alignItems: "center",
      gap: "0.5rem",
      padding: "0.5rem",
      opacity: concluida ? 0.6 : 1,
    }}>
      <input type="checkbox" checked={concluida} readOnly />
      <span style={{
        textDecoration: concluida ? "line-through" : "none",
      }}>
        {titulo}
      </span>
    </div>
  );
}

function TaskList() {
  const tasks = [
    { id: 1, titulo: "Aprender JSX", concluida: true },
    { id: 2, titulo: "Estudar componentes", concluida: false },
    { id: 3, titulo: "Fazer laboratório", concluida: false },
  ];

  return (
    <div>
      <h1>Minhas Tarefas</h1>
      {tasks.map((task) => (
        <TaskItem key={task.id} {...task} />
      ))}
    </div>
  );
}

export default TaskList;
# Criar projeto React com Vite + TypeScript
npm create vite@latest meu-app -- --template react-ts
cd meu-app
npm install
npm run dev

JSX não é HTML. className em vez de class, htmlFor em vez de for, estilo em camelCase. E lembre-se: key é essencial para renderização eficiente de listas.