21. Props para objetos

Tutorial de Props para Objetos en React

Introducción a las Props en React

Las props (abreviatura de propiedades) son la forma principal de pasar datos de un componente padre a un componente hijo en React. Cuando necesitas pasar múltiples valores relacionados, usar objetos como props puede ser más eficiente y organizado.

Tabla de Contenidos

  1. Props Básicas vs Props como Objetos

  2. Pasando Objetos como Props

  3. Desestructuración de Props Objeto

  4. Props con Valores por Defecto

  5. Validación de Props con PropTypes

  6. Props Objeto con TypeScript

  7. Mejores Prácticas








1. Props Básicas vs Props como Objetos

Ejemplo con props individuales:

jsx

// Componente hijo

function UsuarioIndividual(props) {

  return (

    <div className="usuario">

      <h3>{props.nombre}</h3>

      <p>Edad: {props.edad}</p>

      <p>Email: {props.email}</p>

      <p>Rol: {props.rol}</p>

    </div>

  );

}


// Componente padre

function App() {

  return (

    <UsuarioIndividual 

      nombre="Ana García" 

      edad={28} 

      email="ana@email.com" 

      rol="Desarrolladora" 

    />

  );

}





Ejemplo con objeto como prop:

jsx

// Componente hijo

function UsuarioConObjeto(props) {

  return (

    <div className="usuario">

      <h3>{props.usuario.nombre}</h3>

      <p>Edad: {props.usuario.edad}</p>

      <p>Email: {props.usuario.email}</p>

      <p>Rol: {props.usuario.rol}</p>

    </div>

  );

}


// Componente padre

function App() {

  const usuario = {

    nombre: "Ana García",

    edad: 28,

    email: "ana@email.com",

    rol: "Desarrolladora"

  };


  return <UsuarioConObjeto usuario={usuario} />;

}






2. Pasando Objetos como Props-Ejemplo completo:

// ProductoCard.jsx - Componente hijo

function ProductoCard(props) {

  const { producto } = props;

  

  return (

    <div className="card producto-card">

      <img src={producto.imagen} alt={producto.nombre} />

      <div className="card-content">

        <h3>{producto.nombre}</h3>

        <p>{producto.descripcion}</p>

        <div className="producto-info">

          <span className="precio">${producto.precio}</span>

          <span className={`stock ${producto.stock > 0 ? 'disponible' : 'agotado'}`}>

            {producto.stock > 0 ? `${producto.stock} disponibles` : 'Agotado'}

          </span>

        </div>

        <button 

          className="btn-comprar" 

          disabled={producto.stock === 0}

        >

          {producto.stock > 0 ? 'Añadir al carrito' : 'No disponible'}

        </button>

      </div>

    </div>

  );

}// App.jsx - Componente padre

function App() {

  const productoEjemplo = {

    id: 1,

    nombre: "Laptop Gaming Pro",

    descripcion: "Laptop de alto rendimiento para gaming y trabajo",

    precio: 1299.99,

    stock: 15,

    imagen: "https://images.unsplash.com/photo-1603302576837-37561b2e2302",

    categoria: "Electrónicos",

    rating: 4.5,

    especificaciones: {

      procesador: "Intel i7",

      ram: "16GB",

      almacenamiento: "1TB SSD"

    }  };


  return (

    <div className="App">

      <h1>Tienda Online</h1>

      <ProductoCard producto={productoEjemplo} />

    </div>

  );

}











3. Desestructuración de Props Objeto

La desestructuración hace el código más limpio y legible:

jsx

// Opción 1: Desestructuración en los parámetros

function ProductoCard({ producto }) {

  // Ahora podemos usar 'producto' directamente

  return (

    <div className="card">

      <h3>{producto.nombre}</h3>

      {/* ... resto del componente */}

    </div>

  );

}


// Opción 2: Desestructuración anidada

function ProductoCard({ 

  producto: {

    nombre,

    precio,

    stock,

    imagen,

    especificaciones: { procesador, ram }

  }

}) {

  return (

    <div className="card">

      <h3>{nombre}</h3>

      <p>Precio: ${precio}</p>

      <p>Procesador: {procesador}</p>

      <p>RAM: {ram}</p>

      {/* ... resto del componente */}

    </div>

  );

}


// Opción 3: Desestructuración dentro del componente

function ProductoCard(props) {

  const { 

    producto: {

      nombre,

      precio,

      stock,

      // Valores por defecto en desestructuración

      rating = 0,

      descripcion = "Sin descripción disponible"

    }

  } = props;


  return (

    <div className="card">

      <h3>{nombre}</h3>

      <p>{descripcion}</p>

      <p>Precio: ${precio}</p>

      <p>Rating: {"★".repeat(Math.floor(rating))}</p>

    </div>

  );

}










4. Props con Valores por Defecto

Para componentes funcionales:

jsx

function PerfilUsuario({ usuario = {} }) {

  // Valores por defecto con desestructuración

  const {

    nombre = "Usuario Anónimo",

    edad = 0,

    email = "No proporcionado",

    avatar = "https://via.placeholder.com/150",

    activo = false

  } = usuario;


  return (

    <div className={`perfil ${activo ? 'activo' : 'inactivo'}`}>

      <img src={avatar} alt={nombre} />

      <div className="info">

        <h3>{nombre}</h3>

        <p>Edad: {edad}</p>

        <p>Email: {email}</p>

        <span className="estado">

          {activo ? '🟢 En línea' : '⚫ Desconectado'}

        </span>

      </div>

    </div>

  );

}


// O usando defaultProps

PerfilUsuario.defaultProps = {

  usuario: {

    nombre: "Usuario Anónimo",

    edad: 0,

    email: "No proporcionado",

    avatar: "https://via.placeholder.com/150",

    activo: false

  }

};

5. Validación de Props con PropTypes

jsx

import PropTypes from 'prop-types';


function ProductoCard({ producto }) {

  // Componente aquí...

}


ProductoCard.propTypes = {

  producto: PropTypes.shape({

    id: PropTypes.number.isRequired,

    nombre: PropTypes.string.isRequired,

    descripcion: PropTypes.string,

    precio: PropTypes.number.isRequired,

    stock: PropTypes.number,

    imagen: PropTypes.string,

    categoria: PropTypes.oneOf(['Electrónicos', 'Ropa', 'Hogar', 'Otros']),

    rating: PropTypes.number,

    especificaciones: PropTypes.shape({

      procesador: PropTypes.string,

      ram: PropTypes.string,

      almacenamiento: PropTypes.string

    }),

    // Función como propiedad

    onComprar: PropTypes.func

  }).isRequired

};


ProductoCard.defaultProps = {

  producto: {

    stock: 0,

    rating: 0,

    categoria: 'Otros',

    especificaciones: {}

  }

};



6. Props Objeto con TypeScript

tsx

// Definición de tipos/interfaces

interface Especificaciones {

  procesador: string;

  ram: string;

  almacenamiento: string;

  pantalla?: string; // Opcional

}


interface Producto {

  id: number;

  nombre: string;

  descripcion: string;

  precio: number;

  stock: number;

  imagen: string;

  categoria: 'Electrónicos' | 'Ropa' | 'Hogar' | 'Otros';

  rating: number;

  especificaciones: Especificaciones;

  onAgregarCarrito?: () => void; // Función opcional

}


// Props del componente

interface ProductoCardProps {

  producto: Producto;

  destacado?: boolean;

  className?: string;

}


// Componente con TypeScript

function ProductoCard({ 

  producto, 

  destacado = false, 

  className = '' 

}: ProductoCardProps): JSX.Element {

  

  const { 

    nombre, 

    precio, 

    stock, 

    imagen,

    especificaciones: { procesador, ram }

  } = producto;


  return (

    <div className={`producto-card ${destacado ? 'destacado' : ''} ${className}`}>

      {destacado && <span className="badge-destacado">🌟 Destacado</span>}

      <img src={imagen} alt={nombre} />

      <h3>{nombre}</h3>

      <div className="especificaciones">

        <p><strong>Procesador:</strong> {procesador}</p>

        <p><strong>RAM:</strong> {ram}</p>

      </div>

      {/* ... resto del componente */}

    </div>

  );

}

7. Mejores Prácticas

1. Mantén los objetos de props simples

jsx

// ❌ Evita objetos demasiado complejos

<Componente 

  data={{

    usuario: {

      personal: { nombre, edad },

      laboral: { empresa, puesto },

      preferencias: { tema, idioma }

    },

    config: { /* ... */ }

  }}

/>


// ✅ Separa en props más pequeñas

<Componente 

  usuario={usuario}

  config={config}/>


2. Usa desestructuración consistentemente

jsx

// ✅ Más legible

function MiComponente({ usuario, config, onAction }) {

  // Código limpio

}


// ❌ Menos legible

function MiComponente(props) {

  const usuario = props.usuario;

  const config = props.config;

  // Más código...

}

3. Considera el rendimiento con objetos

jsx

// ❌ Esto crea un nuevo objeto en cada render

function App() {

  return <Componente config={{ tema: 'oscuro', sonido: true }} />;

}


// ✅ Mejor: usa useMemo o define fuera del componente

function App() {

  const config = useMemo(() => ({ tema: 'oscuro', sonido: true }), []);

  

  return <Componente config={config} />;

}





4. Ejemplo completo aplicando buenas prácticas

jsx

// components/UserProfile.jsx

import PropTypes from 'prop-types';


function UserProfile({ user, onEdit, isEditable = false }) {

  // Desestructuración con valores por defecto

  const {

    id,

    name = 'Sin nombre',

    email = 'No disponible',

    avatar,

    role = 'user',

    preferences = {},

    createdAt

  } = user;


  const { theme = 'light', notifications = true } = preferences;


  // Formatear fecha

  const joinDate = new Date(createdAt).toLocaleDateString();


  return (

    <div className={`user-profile theme-${theme}`}>

      <div className="profile-header">

        <img 

          src={avatar || 'https://via.placeholder.com/100'} 

          alt={name}

          className="profile-avatar"

        />

        <div className="profile-info">

          <h2>{name}</h2>

          <p className="email">{email}</p>

          <span className={`role-badge role-${role}`}>

            {role.toUpperCase()}

          </span>

        </div>

        {isEditable && (

          <button onClick={onEdit} className="edit-btn">

            ✏️ Editar

          </button>

        )}

      </div>

      

      <div className="profile-details">

        <div className="detail-item">

          <span className="detail-label">Miembro desde:</span>

          <span className="detail-value">{joinDate}</span>

        </div>

        <div className="detail-item">

          <span className="detail-label">Notificaciones:</span>

          <span className="detail-value">

            {notifications ? 'Activadas' : 'Desactivadas'}

          </span>

        </div>

      </div>

    </div>

  );

}


// Validación de props

UserProfile.propTypes = {

  user: PropTypes.shape({

    id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,

    name: PropTypes.string,

    email: PropTypes.string,

    avatar: PropTypes.string,

    role: PropTypes.oneOf(['admin', 'user', 'moderator']),

    preferences: PropTypes.shape({

      theme: PropTypes.oneOf(['light', 'dark']),

      notifications: PropTypes.bool

    }),

    createdAt: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)])

  }).isRequired,

  onEdit: PropTypes.func,

  isEditable: PropTypes.bool

};


UserProfile.defaultProps = {

  isEditable: false,

  user: {

    preferences: {}

  }

};


export default UserProfile;

Ejercicio Práctico

Intenta crear este componente aplicando lo aprendido:

jsx

// Crea un componente RecipeCard que reciba:

// - recipe: objeto con propiedades (title, ingredients[], prepTime, difficulty, tags[])

// - onSave: función opcional

// - isVegetarian: booleano (calculado a partir de ingredients)


// Ejemplo de uso:

const recipe = {

  title: "Ensalada César",

  ingredients: ["lechuga", "pollo", "queso parmesano", "crutones"],

  prepTime: 20, // minutos

  difficulty: "Fácil",

  tags: ["ensalada", "rápido", "almuerzo"],

  servings: 4

};


<RecipeCard recipe={recipe} onSave={handleSaveRecipe} />

Conclusión

Usar objetos como props en React te permite:

  • Agrupar datos relacionados lógicamente

  • Hacer el código más mantenible

  • Facilitar la validación de tipos

  • Mejorar la reutilización de componentes

  • Hacer las interfaces de componentes más claras

Recuerda que cada situación es diferente. Evalúa si usar un objeto como prop es la mejor opción basándote en la complejidad y relación de los datos que necesitas pasar.

¡Ahora estás listo para usar objetos como props de manera efectiva en tus proyectos de React




 **********************************

Props para Objetos en React ☕

📋 Introducción

En React, los props no solo pueden ser valores simples (texto, números, booleanos), sino también objetos completos que contienen múltiples propiedades. Esto es especialmente útil cuando necesitas pasar datos estructurados a tus componentes.

🎯 Objetivos del Tutorial

  • Aprender a pasar objetos como props

  • Entender cómo acceder a propiedades anidadas dentro de objetos

  • Practicar con diferentes formas de recibir props

  • Utilizar desestructuración para simplificar el código

📁 Estructura del Proyecto

text

src/

├── components/

│   ├── Coffee.jsx

│   └── User.jsx

├── App.jsx

├── index.jsx

└── ...





🚀 Paso 1: Configuración del Proyecto

Primero, crea un nuevo proyecto de React o usa uno existente.

Archivo: src/App.jsx

jsx

import React from 'react';

import { User } from './components/User';


function App() {

  return (

    <div>

      <h1>🌟 Tutorial: Props con Objetos en React</h1>

      <User 

        nombre="Ana García" 

        edad={25}

        direccion={{

          calle: "Av. Principal 123",

          ciudad: "Madrid",

          pais: "España"

        }}

      />

    </div>

  );

}


export default App;






🔧 Paso 2: Creando Nuestro Primer Componente

Archivo: src/components/User.jsx

jsx

// Versión 1: Usando props como objeto

export function User(props) {

    return (

        <div style={{ border: '1px solid #ccc', padding: '20px', margin: '10px' }}>

            <h2>👤 Usuario: {props.nombre}</h2>

            <p>📅 Edad: {props.edad} años</p>

            <p>📍 Dirección: {props.direccion.calle}, {props.direccion.ciudad}</p>

        </div>

    );

}

📊 Paso 3: Usando Desestructuración

La desestructuración nos permite extraer valores de objetos de forma más concisa.

Archivo actualizado: src/components/User.jsx

jsx

// Versión 2: Desestructurando props

export function User({ nombre, edad, direccion }) {

    return (

        <div style={{ 

            border: '1px solid #4CAF50', 

            padding: '20px', 

            margin: '10px',

            borderRadius: '10px',

            backgroundColor: '#f9f9f9'

        }}>

            <h2 style={{ color: '#4CAF50' }}>👤 {nombre}</h2>

            <p>🎂 {edad} años</p>

            <p>📍 {direccion.calle}, {direccion.ciudad}, {direccion.pais}</p>

        </div>    );}


🏗️ Paso 4: Desestructuración Anidada

Podemos desestructurar aún más para acceder directamente a las propiedades internas.

Archivo actualizado: src/components/User.jsx

jsx

// Versión 3: Desestructuración anidada

export function User({ 

    nombre, 

    edad, 

    direccion: { calle, ciudad, pais } 

}) {

    return (

        <div style={userCardStyle}>

            <h2 style={{ color: '#2196F3' }}>👤 {nombre}</h2>

            <p>🎂 <strong>{edad}</strong> años</p>

            <div style={addressStyle}>

                <p>🏠 <strong>Calle:</strong> {calle}</p>

                <p>🏙️ <strong>Ciudad:</strong> {ciudad}</p>

                <p>🌍 <strong>País:</strong> {pais}</p>

            </div>

        </div>

    );

}


const userCardStyle = {

    border: '2px solid #2196F3',

    padding: '25px',

    margin: '15px',

    borderRadius: '12px',

    backgroundColor: '#e3f2fd',

    boxShadow: '0 4px 6px rgba(0,0,0,0.1)'

};


const addressStyle = {

    backgroundColor: 'white',

    padding: '15px',

    borderRadius: '8px',

    marginTop: '10px'

};

🔍 Paso 5: Múltiples Usuarios con Datos Complejos

Archivo actualizado: src/App.jsxjsx

import React from 'react';

import { User } from './components/User';


function App() {

  const usuarios = [

    {

      id: 1,

      nombre: "Carlos Rodríguez",

      edad: 30,

      profesion: "Ingeniero de Software",

      direccion: {

        calle: "Calle Mayor 45",

        ciudad: "Barcelona",

        pais: "España",

        codigoPostal: "08001"

      },

      contactos: {

        email: "carlos@email.com",

        telefono: "+34 600 123 456"

      }

    },

    {

      id: 2,

      nombre: "Laura Martínez",

      edad: 28,

      profesion: "Diseñadora UX",

      direccion: {

        calle: "Gran Vía 22",

        ciudad: "Valencia",

        pais: "España",

        codigoPostal: "46001"

      },

      contactos: {

        email: "laura@email.com",

        telefono: "+34 600 987 654"

      }

    }

  ];


  return (

    <div style={appStyle}>

      <header style={headerStyle}>

        <h1>📚 Tutorial: Props para Objetos en React</h1>

        <p>Aprende a trabajar con objetos como props</p>

      </header>

      

      <div style={contentStyle}>

        <h2>👥 Lista de Usuarios</h2>

        {usuarios.map(usuario => (

          <User

            key={usuario.id}

            nombre={usuario.nombre}

            edad={usuario.edad}

            profesion={usuario.profesion}

            direccion={usuario.direccion}

            contactos={usuario.contactos}

          />

        ))}

      </div>

    </div>

  );

}


const appStyle = {

  fontFamily: 'Arial, sans-serif',

  maxWidth: '800px',

  margin: '0 auto',

  padding: '20px'

};


const headerStyle = {

  textAlign: 'center',

  backgroundColor: '#6200ea',

  color: 'white',

  padding: '30px',

  borderRadius: '10px',

  marginBottom: '30px'

};


const contentStyle = {

  backgroundColor: 'white',

  padding: '20px',

  borderRadius: '10px',

  boxShadow: '0 2px 10px rgba(0,0,0,0.1)'

};

export default App;

🎨 Paso 6: Componente Mejorado con Todos los Datos

Archivo actualizado: src/components/User.jsx

jsx

export function User({ 

    nombre, 

    edad, 

    profesion,

    direccion: { calle, ciudad, pais, codigoPostal },

    contactos: { email, telefono }

}) {

    

    // Depuración: ver qué props llegan

    console.log(`Renderizando usuario: ${nombre}`);

    

    return (

        <div style={userCardStyle}>

            <div style={userHeaderStyle}>

                <h2 style={{ margin: 0 }}>👤 {nombre}</h2>

                <span style={ageBadgeStyle}>{edad} años</span>

            </div>

            

            <p style={professionStyle}>💼 {profesion}</p>

            

            <div style={sectionStyle}>

                <h3 style={sectionTitleStyle}>📍 Dirección</h3>

                <p>🏠 {calle}</p>

                <p>🏙️ {ciudad}, {codigoPostal}</p>

                <p>🌍 {pais}</p>

            </div>

            

            <div style={sectionStyle}>

                <h3 style={sectionTitleStyle}>📞 Contacto</h3>

                <p>📧 {email}</p>

                <p>📱 {telefono}</p>

            </div>

        </div>

    );

}


const userCardStyle = {

    border: '2px solid #6200ea',

    padding: '25px',

    margin: '20px 0',

    borderRadius: '12px',

    backgroundColor: '#f3e5f5',

    boxShadow: '0 4px 8px rgba(98, 0, 234, 0.1)',

    transition: 'transform 0.3s ease'

};


const userHeaderStyle = {

    display: 'flex',

    justifyContent: 'space-between',

    alignItems: 'center',

    marginBottom: '15px',

    paddingBottom: '15px',

    borderBottom: '1px solid #ddd'

};


const ageBadgeStyle = {

    backgroundColor: '#6200ea',

    color: 'white',

    padding: '5px 15px',

    borderRadius: '20px',

    fontWeight: 'bold'

};


const professionStyle = {

    backgroundColor: '#e8eaf6',

    padding: '10px',

    borderRadius: '5px',

    margin: '15px 0'

};


const sectionStyle = {

    backgroundColor: 'white',

    padding: '15px',

    borderRadius: '8px',

    margin: '10px 0'

};


const sectionTitleStyle = {

    color: '#6200ea',

    marginTop: '0',

    borderBottom: '2px solid #6200ea',

    paddingBottom: '5px'

};

☕ Paso 7: Ejemplo con Componente Coffee

Archivo: src/components/Coffee.jsx

jsx

export function Coffee({ 

    nombre, 

    precio,

    origen,

    descripcion,

    caracteristicas: { tipo, intensidad, notas, cantidad },

    disponible 

}) {

    return (

        <div style={{

            border: `3px solid ${disponible ? '#4CAF50' : '#f44336'}`,

            padding: '20px',

            margin: '15px',

            borderRadius: '10px',

            backgroundColor: '#fff8e1',

            opacity: disponible ? 1 : 0.7

        }}>

            <div style={{ display: 'flex', justifyContent: 'space-between' }}>

                <h2 style={{ color: '#6d4c41', margin: 0 }}>{nombre}</h2>

                <span style={{

                    backgroundColor: disponible ? '#4CAF50' : '#f44336',

                    color: 'white',

                    padding: '5px 10px',

                    borderRadius: '5px',

                    fontWeight: 'bold'

                }}>

                    {disponible ? 'DISPONIBLE' : 'AGOTADO'}

                </span>

            </div>

            

            <p style={{ color: '#6d4c41', fontSize: '1.2em' }}>

                <strong>💰 Precio:</strong> ${precio}

            </p>

            

            <p>🌍 <strong>Origen:</strong> {origen}</p>

            <p>📝 {descripcion}</p>

            

            <div style={{ backgroundColor: '#ffecb3', padding: '15px', borderRadius: '8px', marginTop: '15px' }}>

                <h3 style={{ color: '#5d4037', marginTop: 0 }}>⚡ Características:</h3>

                <ul style={{ listStyle: 'none', padding: 0 }}>

                    <li>🎯 <strong>Tipo:</strong> {tipo}</li>

                    <li>🔥 <strong>Intensidad:</strong> {'★'.repeat(intensidad)}</li>

                    <li>👃 <strong>Notas:</strong> {notas.join(', ')}</li>

                    <li>📦 <strong>Cantidad:</strong> {cantidad} g</li>

                </ul>

            </div>

        </div>

    );

}









🧪 Paso 8: Usando el Componente Coffee

Archivo actualizado: src/App.jsx

jsx

import React from 'react';

import { User } from './components/User';

import { Coffee } from './components/Coffee';


function App() {

  const usuarios = [/* ... mismos datos anteriores ... */];

  

  const cafes = [

    {

      id: 1,

      nombre: "Arabica Premium",

      precio: 12.99,

      origen: "Colombia",

      descripcion: "Café suave con notas frutales y acidez balanceada",

      caracteristicas: {

        tipo: "Grano Entero",

        intensidad: 3,

        notas: ["Chocolate", "Nuez", "Caramelo"],

        cantidad: 250

      },

      disponible: true

    },

    {

      id: 2,

      nombre: "Robusta Intenso",

      precio: 9.99,

      origen: "Vietnam",

      descripcion: "Café fuerte con alto contenido de cafeína",

      caracteristicas: {

        tipo: "Molido",

        intensidad: 5,

        notas: ["Madera", "Tierra", "Especias"],

        cantidad: 500

      },

      disponible: false

    }

  ];


  return (

    <div style={appStyle}>

      <header style={headerStyle}>

        <h1>📚 Tutorial: Props para Objetos en React</h1>

        <p>Aprende a trabajar con objetos como props</p>

      </header>

      

      <main style={mainStyle}>

        <section style={sectionStyle}>

          <h2 style={sectionTitleStyle}>👥 Lista de Usuarios</h2>

          {usuarios.map(usuario => (

            <User key={usuario.id} {...usuario} />

          ))}

        </section>

        

        <section style={sectionStyle}>

          <h2 style={sectionTitleStyle}>☕ Nuestros Cafés</h2>

          {cafes.map(cafe => (

            <Coffee key={cafe.id} {...cafe} />

          ))}

        </section>

      </main>

      

      <footer style={footerStyle}>

        <p>🎓 Tutorial práctico de React - Props con Objetos</p>

      </footer>

    </div>

  );

}


const mainStyle = {

  display: 'grid',

  gridTemplateColumns: '1fr 1fr',

  gap: '30px',

  margin: '30px 0'

};


const sectionStyle = {

  backgroundColor: 'white',

  padding: '25px',

  borderRadius: '10px',

  boxShadow: '0 2px 10px rgba(0,0,0,0.1)'

};


const sectionTitleStyle = {

  color: '#6200ea',

  borderBottom: '3px solid #6200ea',

  paddingBottom: '10px'

};


const footerStyle = {

  textAlign: 'center',

  marginTop: '30px',

  padding: '20px',

  backgroundColor: '#f5f5f5',

  borderRadius: '8px',

  color: '#666'

};


// ... otros estilos igual que antes ...

⚠️ Buenas Prácticas y Errores Comunes

✅ Correcto

jsx

// Usar desestructuración cuando conocemos las props

function User({ nombre, edad, direccion }) {

  return <p>{nombre} vive en {direccion.ciudad}</p>;

}


// Validar props opcionales

function User({ nombre, direccion = {} }) {

  return <p>{nombre} - {direccion.ciudad || "Ciudad no especificada"}</p>;

}

❌ Incorrecto

jsx

// Acceder sin verificar si existe

function User(props) {

  return <p>{props.direccion.ciudad}</p>; // Error si direccion es undefined

}


// Sintaxis incorrecta para objetos

<User direccion="{ calle: '...' }" /> // ❌ Esto pasa un string!

<User direccion={{ calle: '...' }} /> // ✅ Esto pasa un objeto

🏆 Desafío Final: Componente Libro

Crea un componente Book que muestre:

jsx

<Book 

    titulo="Cien años de soledad"

    autor={{ 

        nombre: "Gabriel García Márquez", 

        nacionalidad: "Colombiano",

        premioNobel: true

    }}

    detalles={{

        paginas: 417,

        genero: "Realismo mágico",

        isbn: "978-3-16-148410-0",

        editorial: "Sudamericana"

    }}

    disponible={true}

    calificacion={4.8}

/>

Requisitos:

  1. Usa desestructuración anidada

  2. Añade emojis apropiados

  3. Muestra un indicador de disponibilidad

  4. Muestra las estrellas de calificación

  5. Incluye console.log para depuración

📚 Resumen de Conceptos Clave

Concepto

Ejemplo

Descripción

Props básicos

<User nombre="Ana" />

Valores simples

Objetos como props

direccion={{calle: "..."}}

Objeto entre llaves dobles

Desestructuración

function User({nombre})

Extrae valores directamente

Desestructuración anidada

{direccion: {ciudad}}

Accede a propiedades internas

Props por defecto

function User({nombre = "Invitado"})

Valores predeterminados

Operador opcional

direccion?.ciudad

Previene errores con undefined

🎓 Puntos Clave para Recordar

  1. Objetos como props permiten agrupar datos relacionados

  2. La desestructuración hace tu código más limpio y legible

  3. Usa console.log(props) para depurar y entender qué datos recibes

  4. El operador ?. es tu amigo para props opcionales

  5. React Developer Tools te ayudan a inspeccionar props en tiempo real

🚀 Próximos Pasos

  1. Practica creando componentes con diferentes estructuras de objetos

  2. Experimenta con props anidados más complejos

  3. Aprende sobre propTypes para validación de tipos

  4. Explora el operador spread para pasar props: <User {...userData} />

¡Feliz codificación! 🎉 Recuerda que la práctica constante es clave para dominar React.

*************************************************************************************************




Tutorial: Props para Objetos en React (Imágenes 21)

Introducción a Props en React

En React, las props (propiedades) son la forma principal de pasar datos de componentes padres a componentes hijos. En este tutorial aprenderemos a pasar objetos completos como props y a acceder a sus propiedades.

Ejercicio 1: Componente Básico con Props

Código de las imágenes 1-3

Usuarios.jsx:

jsx

// Versión inicial - props como parámetros individuales

export function Usuarios({ nombre, edad }) {

  return (

    <h1>{nombre}, tiene {edad}</h1>

  )

}

index.jsx:

jsx

import React from 'react';

import ReactDOM from 'react-dom/client';

import { Usuarios } from './components/Usuarios.jsx';


const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(

  <React.StrictMode>

    <Usuarios nombre="frank" edad={21} />

    <Usuarios nombre="pedro" edad={21} />

    <Usuarios nombre="frank2" />

    <Usuarios nombre="frank3" />

  </React.StrictMode>

);

Resultado esperado:

text

frank, tiene 21

pedro, tiene 21

frank2, tiene

frank3, tiene

Ejercicio 2: Usando Props como Objeto-Código de las imágenes 4-6

Usuarios.jsx (actualizado):

jsx

// Usando props como objeto

export function Usuarios(props) {

  return (

    <div>

      <h1>{props.nombre}</h1>

      <h1>{props.edad}</h1>

    </div>

  )

}

index.jsx (actualizado):

jsx

import React from 'react';

import ReactDOM from 'react-dom/client';

import { Usuarios } from './components/Usuarios.jsx';


const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(

  <React.StrictMode>

    <Usuarios

      nombre="frank"

      edad={21}

    />

  </React.StrictMode>

);

Ejercicio 3: Pasando Objetos como Props

Código de las imágenes 7-9

index.jsx (con objeto complejo):

jsx

import React from 'react';

import ReactDOM from 'react-dom/client';

import { Usuarios } from './components/Usuarios.jsx';


const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(

  <React.StrictMode>

    <Usuarios

      nombre="frank"

      edad={21}

      direccion={{ 

        calle: "calle san martín", 

        ciudad: "Lima", 

        pais: "peru" 

      }}

    />

  </React.StrictMode>

);

Usuarios.jsx (accediendo a objeto anidado):

jsx

export function Usuarios(props) {

  // Para depurar, podemos ver qué recibimos

  console.log(props);

  

  return (

    <div>

      <h1>{props.nombre}</h1>

      <h1>{props.edad} ❤️</h1>

      <h1>{props.direccion.calle}</h1>

    </div>

  )}

Ejercicio Completo: Acceso a Propiedades Anidadas

Versión final con destructuring

Usuarios.jsx (versión optimizada):

jsx

export function Usuarios({ nombre, edad, direccion }) {

  // Destructuring para acceder fácilmente a las props

  return (

    <div>

      <h1>👤 {nombre}</h1>

      <h1>🎂 Edad: {edad} años</h1>

      <h1>📍 Dirección:</h1>

      <ul>

        <li>Calle: {direccion.calle}</li>

        <li>Ciudad: {direccion.ciudad}</li>

        <li>País: {direccion.pais}</li>

      </ul>

    </div>

  )

}

Conceptos Clave Explicados

1. Props como Objeto

jsx

// Componente que recibe props como objeto

function Componente(props) {

  return <div>{props.nombre}</div>

}



2. Destructuring de Props

jsx

// Forma más limpia - destructuring

function Componente({ nombre, edad }) {

  return <div>{nombre} - {edad}</div>

}

3. Objetos Anidados en Props

jsx

// Pasar objeto complejo

<Componente 

  datos={{

    personal: { nombre: "Juan", edad: 25 },

    contacto: { email: "juan@email.com" }

  }}

/>


// Acceder a propiedades anidadas

function Componente({ datos }) {

  return (

    <div>

      <p>{datos.personal.nombre}</p>

      <p>{datos.contacto.email}</p>

    </div>

  )

}

4. Depuración con console.log

jsx

function Componente(props) {

  console.log("Props recibidas:", props);

  console.log("Prop específica:", props.direccion);

  

  return <div>...</div>

}

Buenas Prácticas

  1. Usar destructuring cuando sea posible para mayor claridad

  2. Validar props con PropTypes o TypeScript

  3. Pasar objetos completos cuando haya datos relacionados

  4. Evitar mutar props directamente

Ejercicio Práctico

Crea un componente Perfil que reciba:

  • Un objeto usuario con: nombre, apellido, edad

  • Un objeto contacto con: email, teléfono

  • Un array hobbies con al menos 3 elementos

jsx

// index.jsx

<Perfil

  usuario={{ nombre: "Ana", apellido: "García", edad: 28 }}

  contacto={{ email: "ana@email.com", telefono: "123-456-789" }}

  hobbies={["lectura", "natación", "cocina"]}

/>

Conclusión

Las props en React son fundamentales para la comunicación entre componentes. Pasar objetos como props permite organizar mejor los datos relacionados y hacer el código más mantenible. Recuerda que los objetos pueden anidarse y accederse mediante la notación de punto (objeto.propiedad.subpropiedad).

La depuración con console.log() es una herramienta invaluable para entender qué datos están llegando a tus componentes y cómo están estructurados


Comentarios

Entradas más populares de este blog

11. Creando un proyecto react con create-react-app

29. useEffect

38. 4 Routers