1. JSX — Reglas de Oro
className clave
En JSX usas className en lugar de class. Usar class genera un warning en consola.
{expresión} clave
Las llaves {} ejecutan cualquier expresión JS: variables, ternarios, funciones. No puedes usar if, for ni let directamente dentro del JSX.
<>...</>
Cada componente retorna UN solo elemento raíz. Usa Fragment <></> para agrupar sin agregar un <div> extra al DOM.
<img /> cerrar
En JSX, todos los tags vacíos deben auto-cerrarse: <img />, <br />, <input />.
camelCase
Eventos y atributos en camelCase: onClick, onChange, tabIndex, htmlFor (en lugar de for).
Ejemplo JSX válido
function Saludo({ nombre }) {
  const mayus = nombre.toUpperCase();
  return (
    <>
      <h1 className="titulo">Hola, {mayus}</h1>
      <img src="/foto.jpg" alt="foto" />
    </>
  );
}
2. Componentes
PascalCase clave
El nombre SIEMPRE empieza con Mayúscula. <card> es HTML. <Card> es React.
function
Un componente es una función que recibe props y retorna JSX. Nada más.
export default
Para usarlo en otro archivo: export default MiComp. Importar: import MiComp from './MiComp'.
<Comp />
Se usa como etiqueta HTML. React ejecuta la función y muestra el JSX que retorna.
Composición
Los componentes pueden incluir otros componentes. App es el componente raíz que contiene a todos los demás.
Anatomía de un componente
// MiBoton.jsx
function MiBoton({ texto, color }) {
  return (
    <button className={`btn btn-${color}`}>
      {texto}
    </button>
  );
}
export default MiBoton;

// Uso en App.jsx:
<MiBoton texto="Guardar" color="blue" />
3. Props
prop={valor} clave
Se pasan como atributos. Strings con "", todo lo demás con {}: números, booleanos, arrays, objetos, funciones.
{ nombre } clave
Destructuring en el parámetro. Más limpio que props.nombre. Es la forma estándar en React moderno.
children
Prop especial. Contiene lo que pongas entre las etiquetas del componente. Ideal para layouts, modales y tarjetas contenedoras.
prop = default
function Btn({ color = "blue" }) — si el padre no pasa esa prop, usa el valor por defecto.
solo lectura
❌ NUNCA modifiques las props. Son inmutables. Para datos que deben cambiar, usa useState.
Props + children en acción
function Card({ titulo, children }) {
  return (
    <div className="card">
      <h2>{titulo}</h2>
      <div>{children}</div>
    </div>
  );
}

// Uso:
<Card titulo="Perfil">
  <p>Contenido aquí</p>
</Card>
4. useState Hook
import clave
import { useState } from 'react' — Es un Hook. Siempre se importa con llaves. Solo dentro de componentes React.
[val, setVal] clave
Array destructuring: el primer elemento es el valor actual, el segundo es la función para actualizarlo.
setValor()
Llamar a la función dispara un re-render. React actualiza la UI con el nuevo valor automáticamente.
prev => prev+1
Cuando el nuevo estado depende del anterior, usa la forma funcional: setN(prev => prev + 1). Más seguro y confiable.
❌ mutar
NUNCA hagas estado.push() ni estado.prop = x. La mutación directa no dispara re-render. Siempre crea un nuevo valor.
Contador — el ejemplo clásico
import { useState } from 'react';

function Contador() {
  const [cuenta, setCuenta] = useState(0);

  return (
    <div>
      <p>Valor: {cuenta}</p>
      <button onClick={() => setCuenta(prev => prev + 1)}>
        +1
      </button>
      <button onClick={() => setCuenta(0)}>
        Reset
      </button>
    </div>
  );
}
5. Renderizado Condicional
condición && clave
Si la condición es true, muestra el elemento. Si es false, no renderiza nada. Perfecto para mostrar/ocultar.
cond ? A : B clave
Ternario: elige entre dos elementos distintos según una condición. Para decidir qué mostrar, no solo si mostrar.
early return
Retorna antes del JSX principal. Ideal para estados de carga o datos vacíos: if (!datos) return <p>Cargando...</p>
className cond.
className={activo ? "bg-green-500" : "bg-gray-500"} — Cambiar clases de Tailwind según estado es muy común.
Los 3 patrones en acción
// 1. && — mostrar o no mostrar
{estaLogueado && <BienvenidaMsg />}

// 2. Ternario — uno u otro
{cargando
  ? <Spinner />
  : <ListaArticulos />}

// 3. Early return — salida temprana
if (!usuario) return <p>Sin sesión</p>;
return <Dashboard user={usuario} />;
6. Listas con .map()
.map() clave
Transforma un array de datos en un array de elementos JSX. Es la forma estándar de renderizar listas en React.
key obligatorio
Cada elemento del .map() DEBE tener una prop key única. React la usa para optimizar actualizaciones.
item.id
Usa el id del dato como key. Evita el índice del array salvo en listas estáticas que no se reordenan nunca.
.filter()
Encadena .filter() antes de .map() para mostrar solo los elementos que cumplen una condición.
Renderizar array de objetos
const articulos = [
  { id: 1, titulo: "React Hooks", autor: "Ana" },
  { id: 2, titulo: "Tailwind CSS", autor: "Luis" },
];

// En el JSX del componente:
<ul>
  {articulos.map(art => (
    <ArticleCard
      key={art.id}
      titulo={art.titulo}
      autor={art.autor}
    />
  ))}
</ul>
7. Manejo de Eventos
onClick clave
onClick={handleClick} — Pasa la referencia, sin paréntesis. onClick={handleClick()} la ejecutaría al renderizar, no al hacer click.
() => fn(arg)
Si necesitas pasar argumentos, envuelve en arrow function: onClick={() => handleEliminar(item.id)}.
onChange
Para inputs: onChange={e => setValor(e.target.value)}. e.target.value contiene el texto actual del input.
onSubmit
Siempre llama e.preventDefault() dentro del handler para evitar que el formulario recargue la página.
Input controlado + formulario
function FormBusqueda() {
  const [query, setQuery] = useState("");

  function handleSubmit(e) {
    e.preventDefault(); // ← evita recarga de página
    console.log("Buscando:", query);
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        value={query}
        onChange={e => setQuery(e.target.value)}
      />
      <button>Buscar</button>
    </form>
  );
}
8. Reglas de los Hooks
❌ en if/for
Los Hooks NO pueden ir dentro de if, for, ni funciones anidadas. Siempre en el nivel superior del componente.
✅ nivel raíz
React necesita que el orden de llamada sea siempre el mismo entre renders. Por eso deben ir al inicio, sin condiciones.
use*
Los Hooks solo funcionan en componentes React o en custom hooks. Todos los custom hooks empiezan con use: useContador, useAuth.
useState
Estado local del componente. Ya lo vimos — ¡lo más importante!
useEffect clase 03
Efectos secundarios: fetch de datos, suscripciones, timers.
useContext clase 04
Estado global sin pasar props manualmente por cada nivel.
❌ Mal vs ✅ Bien
// ❌ MAL — Hook dentro de un if
function Componente() {
  if (condicion) {
    const [val, setVal] = useState(0); // ERROR
  }
}

// ✅ BIEN — Hook al nivel raíz
function Componente() {
  const [val, setVal] = useState(0); // ✅
  if (condicion) { /* usa val aquí */ }
}