Las props son el mecanismo de React para enviar datos de un componente padre a un componente hijo.
Cuando construyes una interfaz, un componente solo puede mostrar información útil si recibe datos desde fuera. Las props son exactamente eso: la forma en que un componente padre le entrega información a su hijo.
¿Qué son las props?
Prop es una abreviación de property (propiedad). En React, las props funcionan como los atributos de una etiqueta HTML, pero tú defines su nombre y su valor.
Un componente padre escribe las props al usar el componente hijo. El componente hijo las recibe como un objeto llamado props.
Sintaxis básica
Así se ve la estructura general para pasar y recibir props:
En el padre (donde usas el componente):
<NombreComponente nombreProp={valor} />
En el hijo (donde defines el componente):
function NombreComponente(props) {
return <p>{props.nombreProp}</p>;
}
El objeto props contiene todas las propiedades que el padre le envió. Las accedes con notación de punto: props.nombreProp.
Ejemplo 1: Tarjeta de producto simple
Imagina que estás construyendo un catálogo al estilo Mercado Libre. Quieres mostrar el nombre y el precio de un producto.
Componente hijo — TarjetaProducto.jsx:
function TarjetaProducto(props) {
return (
<div className="tarjeta">
<h2>{props.nombre}</h2>
<p>Precio: ${props.precio.toLocaleString("es-MX")}</p>
</div>
);
}
Componente padre — App.jsx:
function App() {
return (
<div>
<TarjetaProducto nombre="Tenis Nike Air Max" precio={2850} />
<TarjetaProducto nombre="Licuadora Oster" precio={1199} />
</div>
);
}
Resultado en pantalla:
Tenis Nike Air Max
Precio: $2,850
Licuadora Oster
Precio: $1,199
Observa que el mismo componente TarjetaProducto se reutiliza dos veces con datos distintos. Eso es el poder de las props.
Desestructuración de props
Escribir props.nombre, props.precio y props.disponible en cada línea puede volverse repetitivo. Puedes usar desestructuración directamente en los parámetros de la función.
Sin desestructuración:
function TarjetaProducto(props) {
return <h2>{props.nombre}</h2>;
}
Con desestructuración:
function TarjetaProducto({ nombre, precio }) {
return (
<div>
<h2>{nombre}</h2>
<p>Precio: ${precio.toLocaleString("es-MX")}</p>
</div>
);
}
El resultado es exactamente el mismo, pero el código es más limpio y fácil de leer.
Ejemplo 2: Tarjeta completa con más props
Ahora agrega imagen, calificación y disponibilidad al catálogo.
Componente hijo:
function TarjetaProducto({ nombre, precio, imagen, calificacion, disponible }) {
return (
<div className="tarjeta">
<img src={imagen} alt={nombre} />
<h2>{nombre}</h2>
<p>Precio: ${precio.toLocaleString("es-MX")}</p>
<p>Calificación: {calificacion} / 5</p>
<p>{disponible ? "En stock" : "Agotado"}</p>
</div>
);
}
Componente padre:
function App() {
return (
<div>
<TarjetaProducto
nombre="Cafetera Nescafé Dolce Gusto"
precio={1599}
imagen="cafetera.jpg"
calificacion={4.7}
disponible={true}
/>
<TarjetaProducto
nombre="Pantuflas Flexi"
precio={349}
imagen="pantuflas.jpg"
calificacion={4.2}
disponible={false}
/>
</div>
);
}
Resultado en pantalla:
Cafetera Nescafé Dolce Gusto
Precio: $1,599
Calificación: 4.7 / 5
En stock
Pantuflas Flexi
Precio: $349
Calificación: 4.2 / 5
Agotado
Fíjate en el ternario disponible ? "En stock" : "Agotado". Es exactamente la lógica que aprendiste en la lección anterior sobre expresiones dentro de JSX.
Props con valores por defecto
A veces, un prop puede ser opcional. Si el padre no lo envía, tu componente puede usar un valor por defecto.
Hay dos formas de definir valores por defecto:
Forma 1 — Desestructuración con valor asignado:
function TarjetaProducto({ nombre, precio, calificacion = 0, disponible = true }) {
return (
<div>
<h2>{nombre}</h2>
<p>Precio: ${precio.toLocaleString("es-MX")}</p>
<p>Calificación: {calificacion} / 5</p>
<p>{disponible ? "En stock" : "Agotado"}</p>
</div>
);
}
Si el padre no envía calificacion, el componente usa 0. Si no envía disponible, usa true.
Forma 2 — defaultProps (menos común en código moderno):
TarjetaProducto.defaultProps = {
calificacion: 0,
disponible: true,
};
La primera forma es la más usada en proyectos modernos con React 17 en adelante.
Ejemplo 3: Renderizado con una lista
En catálogos reales, los productos vienen de un arreglo de objetos. Puedes combinar .map() con props para renderizar múltiples tarjetas.
const productos = [
{ id: 1, nombre: "Mochila Samsonite", precio: 1850, calificacion: 4.5, disponible: true },
{ id: 2, nombre: "Audífonos Sony", precio: 2200, calificacion: 4.8, disponible: true },
{ id: 3, nombre: "Báscula digital", precio: 499, calificacion: 3.9, disponible: false },
];
function App() {
return (
<div>
{productos.map((producto) => (
<TarjetaProducto
key={producto.id}
nombre={producto.nombre}
precio={producto.precio}
calificacion={producto.calificacion}
disponible={producto.disponible}
/>
))}
</div>
);
}
El prop key es especial. React lo usa internamente para rastrear cada elemento de la lista. Siempre debes incluirlo cuando usas .map(). No aparece en el componente hijo porque React lo reserva para su propio uso.
Tipos de datos que puedes pasar como prop
| Tipo de dato | Ejemplo en JSX |
|---|---|
| Texto (string) | nombre="Liverpool" |
| Número | precio={1299} |
| Booleano | disponible={true} |
| Arreglo | etiquetas={["nuevo", "oferta"]} |
| Objeto | vendedor={{ nombre: "FEMSA", ciudad: "Monterrey" }} |
| Función | onClick={manejarClick} |
Los strings son el único tipo que puedes pasar sin llaves {}. Todos los demás tipos requieren llaves.
Errores comunes
Error 1: Pasar un número como string.
// ❌ Incorrecto — precio llega como texto "1299", no como número
<TarjetaProducto precio="1299" />
// ✅ Correcto — precio llega como número 1299
<TarjetaProducto precio={1299} />
Si intentas llamar precio.toLocaleString() sobre un string, React lanza un error.
Error 2: Olvidar que las props son de solo lectura.
Dentro del componente hijo, nunca modifiques una prop directamente. Las props son inmutables.
// ❌ Incorrecto — esto rompe el flujo de datos de React
function TarjetaProducto({ precio }) {
precio = precio * 0.9; // No hagas esto
return <p>${precio}</p>;
}
// ✅ Correcto — crea una variable nueva
function TarjetaProducto({ precio }) {
const precioConDescuento = precio * 0.9;
return <p>${precioConDescuento.toLocaleString("es-MX")}</p>;
}
Error 3: Confundir key con un prop normal.
// ❌ Incorrecto — intentar usar key dentro del componente hijo
function TarjetaProducto({ key, nombre }) { // key siempre es undefined aquí
return <p>{key} - {nombre}</p>;
}
// ✅ Correcto — si necesitas el id, pásalo como prop separado
<TarjetaProducto key={producto.id} id={producto.id} nombre={producto.nombre} />
key no es accesible dentro del componente. Si necesitas el identificador, pásalo como un prop con otro nombre como id.
Flujo de datos en React
React sigue un flujo de datos unidireccional: los datos van del padre al hijo, nunca al revés. Este principio se llama one-way data flow.
Si un componente hijo necesita comunicarse hacia arriba, no lo hace con props directamente. Eso se resuelve con funciones que el padre le pasa al hijo como prop. Ese tema se cubre en la lección de eventos.
Puntos clave
- Las props permiten reutilizar un componente con datos distintos en cada uso.
- Desestructurar props en los parámetros hace el código más limpio.
- Los valores por defecto evitan errores cuando un prop es opcional.
- Usa
keysiempre que renderices listas con.map(), pero no lo uses como prop normal dentro del hijo. - Las props son inmutables: nunca las modifiques dentro del componente hijo.