Saltar al contenido
schedule 12 min React

Props y children

En la lección anterior creaste componentes, pero todos mostraban datos fijos. Tres <ProductCard /> mostraban exactamente el mismo café. Eso no es muy útil. Necesitas una forma de pasarle datos diferentes a cada componente — y para eso existen las props.

Si recuerdas la sección de Lógica de Programación, las funciones recibían parámetros para trabajar con datos diferentes cada vez que se llamaban. Las props son exactamente lo mismo: los parámetros de un componente React.

¿Qué son las props?

Las props (abreviatura de "properties") son la forma de pasar datos de un componente padre a un componente hijo. Se pasan como atributos en el JSX y se reciben como un objeto en la función del componente.

src/components/ProductCard.jsx
// El componente recibe props como parámetro
function ProductCard(props) {
    return (
        <div className="card">
            <h3>{props.nombre}</h3>
            <p>{props.descripcion}</p>
            <span className="precio">{props.precio} €</span>
        </div>
    )
}

export default ProductCard
src/App.jsx
import ProductCard from './components/ProductCard'

function App() {
    return (
        <div>
            <h1>Café Estelar</h1>
            <ProductCard
                nombre="Café Nebulosa"
                descripcion="Espresso con leche de avena y canela estelar."
                precio={3.5}
            />
            <ProductCard
                nombre="Latte Cósmico"
                descripcion="Café con leche, vainilla y polvo de estrellas."
                precio={4.2}
            />
            <ProductCard
                nombre="Mocha Intergaláctico"
                descripcion="Chocolate negro, espresso y crema de la Vía Láctea."
                precio={4.8}
            />
        </div>
    )
}

export default App

Cada <ProductCard /> recibe datos diferentes a través de las props, pero usa el mismo componente. Un componente, tres resultados distintos. Eso es reutilización.

Desestructurar props

Escribir props.nombre, props.descripcion, props.precio es repetitivo. La forma estándar en React es desestructurar las props directamente en el parámetro de la función — igual que hacías con objetos en JavaScript:

src/components/ProductCard.jsx
// ✅ Desestructuración: más limpio y directo
function ProductCard({ nombre, descripcion, precio }) {
    return (
        <div className="card">
            <h3>{nombre}</h3>
            <p>{descripcion}</p>
            <span className="precio">{precio} €</span>
        </div>
    )
}

export default ProductCard

Esto es equivalente a lo anterior pero más conciso. Verás esta sintaxis en prácticamente todo el código React del mundo real.

Props por defecto

A veces quieres que una prop tenga un valor si el padre no la pasa. Puedes definir valores por defecto directamente en la desestructuración:

src/components/ProductCard.jsx
function ProductCard({ nombre, descripcion, precio = 0, disponible = true }) {
    return (
        <div className="card" style={{ opacity: disponible ? 1 : 0.5 }}>
            <h3>{nombre}</h3>
            <p>{descripcion}</p>
            <span className="precio">{precio.toFixed(2)} €</span>
            {!disponible && <p className="agotado">Agotado</p>}
        </div>
    )
}

export default ProductCard
// precio usa el valor por defecto (0), disponible usa el suyo (true)
<ProductCard nombre="Agua Estelar" descripcion="Agua del manantial de Orión." />

// Aquí pasamos disponible como false
<ProductCard
    nombre="Café Eclipse"
    descripcion="Edición limitada."
    precio={6.0}
    disponible={false}
/>

Tipos de datos en props

Las props pueden ser de cualquier tipo de JavaScript. Los strings se pasan con comillas y el resto con llaves:

// String: con comillas
<Componente nombre="Astronauta" />

// Número: con llaves
<Componente precio={3.5} />

// Booleano: con llaves (o solo el nombre para true)
<Componente disponible={true} />
<Componente disponible />        {/* equivale a true */}

// Array: con llaves
<Componente ingredientes={['café', 'leche', 'canela']} />

// Objeto: con llaves (dobles llaves = llave JSX + objeto literal)
<Componente estilo={{ color: 'red', fontSize: '14px' }} />

// Función: con llaves
<Componente onClick={() => alert('¡Hola!')} />

Las props son de solo lectura

Esto es fundamental: un componente nunca debe modificar sus props. Las props son datos que vienen del padre y el hijo solo puede leerlas.

function ProductCard({ precio }) {
    // ❌ NUNCA hagas esto
    precio = precio * 1.21

    // ✅ Crea una nueva variable
    const precioConIva = precio * 1.21

    return <p>{precioConIva} €</p>
}

Si necesitas un dato que cambie, eso es estado — lo veremos en la siguiente lección.

Children: contenido entre etiquetas

Hay una prop especial llamada children. Es todo lo que pones entre las etiquetas de apertura y cierre de un componente:

src/components/Card.jsx
// children es lo que va dentro de las etiquetas del componente
function Card({ children, titulo }) {
    return (
        <div className="card">
            <h3>{titulo}</h3>
            <div className="card__body">
                {children}
            </div>
        </div>
    )
}

export default Card
src/App.jsx
import Card from './components/Card'

function App() {
    return (
        <div>
            <Card titulo="Café Nebulosa">
                <p>Espresso con leche de avena y canela estelar.</p>
                <span>3.50 €</span>
            </Card>

            <Card titulo="Oferta del día">
                <p>¡2x1 en todos los lattes!</p>
                <button>Ver oferta</button>
            </Card>
        </div>
    )
}

export default App

children es perfecto para crear componentes "contenedor" que no saben de antemano qué contenido van a tener. Un componente Card, un Modal, un Layout — todos usan children para envolver contenido arbitrario.

Composición con props y children

Vamos a crear un ejemplo más completo que combine props y children:

src/components/Badge.jsx
function Badge({ texto, color = '#61DAFB' }) {
    return (
        <span style={{
            background: color,
            color: '#1a1a2e',
            padding: '2px 8px',
            borderRadius: '4px',
            fontSize: '0.75rem',
            fontWeight: 'bold'
        }}>
            {texto}
        </span>
    )
}

export default Badge
src/components/ProductCard.jsx
import Badge from './Badge'

function ProductCard({ nombre, descripcion, precio, categoria }) {
    return (
        <div className="card">
            <div className="card__header">
                <h3>{nombre}</h3>
                <Badge texto={categoria} />
            </div>
            <p>{descripcion}</p>
            <span className="precio">{precio.toFixed(2)} €</span>
        </div>
    )
}

export default ProductCard
src/App.jsx
import ProductCard from './components/ProductCard'

function App() {
    return (
        <div style={{ maxWidth: '600px', margin: '0 auto', padding: '2rem' }}>
            <h1 style={{ color: '#61DAFB' }}>Café Estelar</h1>

            <ProductCard
                nombre="Café Nebulosa"
                descripcion="Espresso con leche de avena y canela estelar."
                precio={3.5}
                categoria="Espresso"
            />
            <ProductCard
                nombre="Latte Cósmico"
                descripcion="Café con leche, vainilla y polvo de estrellas."
                precio={4.2}
                categoria="Latte"
            />
            <ProductCard
                nombre="Té Supernova"
                descripcion="Té verde con jengibre y miel del asteroide B-612."
                precio={3.0}
                categoria="Té"
            />
        </div>
    )
}

export default App

Fíjate en la cadena: AppProductCardBadge. Los datos fluyen siempre de arriba a abajo, de padre a hijo. Este flujo unidireccional es una de las ideas centrales de React y hace que tu código sea predecible — siempre sabes de dónde vienen los datos.

Resumen

  • Las props son la forma de pasar datos de un componente padre a un componente hijo. Son como los parámetros de una función.
  • Se reciben desestructurándolas en el parámetro de la función: function Card({ titulo, precio }).
  • Puedes definir valores por defecto directamente en la desestructuración.
  • Las props son de solo lectura — nunca las modifiques directamente.
  • children es una prop especial que contiene todo lo que pones entre las etiquetas de apertura y cierre del componente.
  • Los datos fluyen siempre de arriba a abajo (padre → hijo). Esto se llama flujo unidireccional.

En la siguiente lección aprenderás useState — el hook que permite a tus componentes tener datos que cambian con el tiempo y hacen que la interfaz reaccione.

code

Equipo galáctico con props y children

Fácil schedule 20 min

Crea un componente MemberCard que reciba las siguientes props: nombre, rol, avatar (URL de imagen), y activo (booleano, por defecto true). Si activo es false, la tarjeta debe mostrarse con opacidad reducida.

  • Crea un componente Section que reciba un titulo y use children para envolver su contenido.
  • En App.jsx, usa Section con el título "Nuestro equipo" y dentro coloca al menos tres MemberCard con datos diferentes. Uno de ellos debe tener activo={false}.
  • Para las imágenes puedes usar placeholders como https://i.pravatar.cc/150?img=1 (cambia el número para diferentes avatares).
lightbulb Pistas

Desestructura las props directamente en el parámetro: function MemberCard( nombre, rol, avatar, activo = true ). Para la opacidad condicional, usa estilos en línea: style={{ "{{" }} opacity: activo ? 1 : 0.5 {{ "}}" }}. El componente Section recibe children y lo renderiza dentro de un contenedor con un <h2> para el título.

Newsletter

Recibe nuevos cursos, actualizaciones, artículos del blog y promociones en tu correo.