← React & TypeScript

Fundamentos de React

¿Qué es un componente en React y qué son las props?

Ver respuesta — intenta responderla en voz alta primero

Un componente es una función que recibe props y devuelve JSX: una pieza reutilizable de UI. Las props son los datos que el componente padre le pasa al hijo; son de solo lectura y fluyen siempre en una dirección, de padre a hijo.

Piensa en un componente como una pieza de LEGO: lo defines una vez y lo usas muchas veces con distintos datos. Una app de React es un árbol de componentes compuestos unos dentro de otros. Las props (de properties) son el mecanismo para pasarle información a un componente:

  • Son como los argumentos de una función: el padre "llama" al hijo con ciertos valores.
  • Son de solo lectura: un componente nunca debe modificar sus props. Si necesita un dato que cambia, eso es estado, no props.
  • Flujo unidireccional: los datos bajan del padre al hijo. Si un hijo necesita "avisar" algo hacia arriba, el padre le pasa una función por props y el hijo la llama.
  • Composición: en lugar de herencia, React favorece componer componentes pequeños. La prop especial children permite que un componente envuelva a otros.
  • Con TypeScript: tipar las props con un type documenta el contrato del componente y evita errores al usarlo.
import type { ReactNode } from "react";

// Las props se tipan con un type: este es el "contrato" del componente
type SaludoProps = { nombre: string; edad?: number };

function Saludo({ nombre, edad }: SaludoProps) {
  return <p>Hola, {nombre}{edad !== undefined && ` (${edad} años)`}</p>;
}

// Composición: Tarjeta no sabe qué contiene, solo envuelve a sus children
type TarjetaProps = { titulo: string; children: ReactNode };

function Tarjeta({ titulo, children }: TarjetaProps) {
  return (
    <section className="tarjeta">
      <h2>{titulo}</h2>
      {children}
    </section>
  );
}

function App() {
  return (
    <Tarjeta titulo="Equipo">
      {/* El mismo componente, reutilizado con distintas props */}
      <Saludo nombre="Ana" edad={28} />
      <Saludo nombre="Luis" />
    </Tarjeta>
  );
}

// Salida esperada:
// Equipo / Hola, Ana (28 años) / Hola, Luis

Intentar mutar las props dentro del hijo:

// MAL: reasignar la prop no re-renderiza y rompe el contrato
function Contador({ contador }: { contador: number }) {
  return <button onClick={() => (contador = contador + 1)}>{contador}</button>;
}

// BIEN: el hijo avisa con una función; el padre (dueño del dato) actualiza
type Props = { contador: number; onIncrementar: () => void };
function ContadorBien({ contador, onIncrementar }: Props) {
  return <button onClick={onIncrementar}>{contador}</button>;
}

"Un componente es una función que recibe props y devuelve JSX; es la unidad básica de reutilización en React. Las props son los datos que el padre le pasa al hijo, como los argumentos de una función, y son de solo lectura: un componente nunca debe modificarlas. Los datos fluyen en una sola dirección, de padre a hijo, y cuando el hijo necesita comunicar algo hacia arriba, recibe una función por props y la ejecuta. En lugar de herencia, React usa composición: armo interfaces complejas combinando componentes pequeños, muchas veces con la prop children."

Reto rápido

Crea un componente Boton que reciba por props un texto: string, una prop opcional deshabilitado?: boolean y una función onPresionar: () => void. Úsalo desde un componente App que muestre dos botones: uno activo y uno deshabilitado.

Ver solución
type BotonProps = {
  texto: string;
  deshabilitado?: boolean;
  onPresionar: () => void;
};

function Boton({ texto, deshabilitado = false, onPresionar }: BotonProps) {
  return (
    <button disabled={deshabilitado} onClick={onPresionar}>
      {texto}
    </button>
  );
}

function App() {
  return (
    <>
      <Boton texto="Guardar" onPresionar={() => console.log("guardado")} />
      <Boton texto="Eliminar" deshabilitado onPresionar={() => {}} />
    </>
  );
}