Pasar propiedades de hijo a padre en React
DUDA 1: ¿Qué es const saludar = (nombre) => { ... }?
Explicación simple:
const saludar = (nombre) => {
alert(`Hola ${nombre}`);
};
const saludar = (nombre) => {
alert(`Hola ${nombre}`);
};Esto SÍ define una función. Piensa en const saludar como un nombre para la función. Es equivalente a:
function saludar(nombre) {
alert(`Hola ${nombre}`);
}Analogía:
const saludar = "Voy a guardar algo en una caja llamada 'saludar'"
= (nombre) => { alert(...) } = "Lo que guardo es una función que recibe 'nombre' y muestra alerta"
const saludar = "Voy a guardar algo en una caja llamada 'saludar'"
= (nombre) => { alert(...) } = "Lo que guardo es una función que recibe 'nombre' y muestra alerta"
Cómo se puede usar:
// Opción 1: Llamarla directamente
saludar("Juan"); // Muestra: "Hola Juan"
// Opción 2: Pasar la función como referencia
const miFuncion = saludar; // Guarda la función en otra variable
miFuncion("Ana"); // Muestra: "Hola Ana"
// Opción 1: Llamarla directamente
saludar("Juan"); // Muestra: "Hola Juan"
// Opción 2: Pasar la función como referencia
const miFuncion = saludar; // Guarda la función en otra variable
miFuncion("Ana"); // Muestra: "Hola Ana"📌 DUDA 2: ¿Por qué a veces se usa () => saludar("Mundo") y a veces saludar?
Esta es la clave para entender React. Hay dos casos diferentes:
CASO A: Cuando la función NO necesita parámetros
// En el padre
const mostrarMensaje = () => {
alert("¡Hola!");
};
// En el return
<Accion
accion={mostrarMensaje} // ← SIN paréntesis, SIN arrow function adicional
texto="Saludar"
/>
// En el padre
const mostrarMensaje = () => {
alert("¡Hola!");
};
// En el return
<Accion
accion={mostrarMensaje} // ← SIN paréntesis, SIN arrow function adicional
texto="Saludar"
/>¿Por qué?
mostrarMensajeya es una función lista para ejecutarNo necesita parámetros adicionales
Solo pasamos la referencia (el "teléfono" de la función)
CASO B: Cuando la función SÍ necesita parámetros
// En el padre
const saludar = (nombre) => {
alert(`Hola ${nombre}`);
};
// En el return
<Accion
accion={() => saludar("Mundo")} // ← CON arrow function que envuelve
texto="Saludar"
/>
// En el padre
const saludar = (nombre) => {
alert(`Hola ${nombre}`);
};
// En el return
<Accion
accion={() => saludar("Mundo")} // ← CON arrow function que envuelve
texto="Saludar"
/>¿Por qué la arrow function extra?
saludar("Mundo")→ Ejecuta inmediatamente (¡ERROR!)() => saludar("Mundo")→ Crea una nueva función que, cuando se ejecute, llamará asaludar("Mundo")
🎯 Comparación Visual:
// EJEMPLO 1: Sin parámetros
const saludarSimple = () => {
alert("¡Hola Mundo!");
};
// En el return → PASO DIRECTO
<Accion accion={saludarSimple} />
// EJEMPLO 2: Con parámetros
const saludarConNombre = (nombre) => {
alert(`Hola ${nombre}`);
};
// En el return → ENVOLVIENDO CON ARROW FUNCTION
<Accion accion={() => saludarConNombre("Mundo")} />
// EJEMPLO 1: Sin parámetros
const saludarSimple = () => {
alert("¡Hola Mundo!");
};
// En el return → PASO DIRECTO
<Accion accion={saludarSimple} />
// EJEMPLO 2: Con parámetros
const saludarConNombre = (nombre) => {
alert(`Hola ${nombre}`);
};
// En el return → ENVOLVIENDO CON ARROW FUNCTION
<Accion accion={() => saludarConNombre("Mundo")} />🔍 Entendiendo la Diferencia con Ejemplos:
Ejemplo 1: Lo que NO debes hacer (ERROR COMÚN)
// ❌ MAL: Se ejecuta inmediatamente al renderizar
<Accion accion={saludar("Mundo")} />
// Esto muestra la alerta INMEDIATAMENTE al cargar la página
// ✅ BIEN: Se crea una función que se ejecutará después
<Accion accion={() => saludar("Mundo")} />
// Esto muestra la alerta SOLO cuando hagan clic
// ❌ MAL: Se ejecuta inmediatamente al renderizar
<Accion accion={saludar("Mundo")} />
// Esto muestra la alerta INMEDIATAMENTE al cargar la página
// ✅ BIEN: Se crea una función que se ejecutará después
<Accion accion={() => saludar("Mundo")} />
// Esto muestra la alerta SOLO cuando hagan clicEjemplo 2: Alternativa correcta
// También podrías hacer esto:
const saludarMundo = () => {
saludar("Mundo");
};
// Y luego pasar la referencia
<Accion accion={saludarMundo} />
// También podrías hacer esto:
const saludarMundo = () => {
saludar("Mundo");
};
// Y luego pasar la referencia
<Accion accion={saludarMundo} />🧠 Regla Muy Simple para Recordar:
// Si tu función original NO tiene parámetros:
<Componente funcion={nombreFuncion} />
// Si tu función original SÍ tiene parámetros:
<Componente funcion={() => nombreFuncion(parametro)} />
// Si tu función original NO tiene parámetros:
<Componente funcion={nombreFuncion} />
// Si tu función original SÍ tiene parámetros:
<Componente funcion={() => nombreFuncion(parametro)} />🎮 Ejemplo Práctico para Entender:
Imagina estas funciones:
// Función A: No necesita información adicional
const encenderLuz = () => {
console.log("Luz encendida");
};
// Función B: Necesita saber QUÉ luz encender
const encenderLuzEspecifica = (nombreLuz) => {
console.log(`Encendiendo: ${nombreLuz}`);
};Cómo las pasarías a un botón:
// Botón 1: Solo encender (sin especificar cuál)
<Boton
accion={encenderLuz} // ← Directo, no necesita preparación
texto="Encender"
/>
// Botón 2: Encender luz específica
<Boton
accion={() => encenderLuzEspecifica("Sala")} // ← Prepara la llamada
texto="Encender luz de Sala"
/>📚 Resumen Final:
const miFuncion = () => { ... } → Sí define una función
miFuncion → Es la referencia a la función (se pasa cuando no hay parámetros)
() => miFuncion(param) → Crea una nueva función que llama a la original con parámetros
miFuncion(param) → Ejecuta inmediatamente (generalmente ERROR en React)
const miFuncion = () => { ... } → Sí define una función
miFuncion → Es la referencia a la función (se pasa cuando no hay parámetros)
() => miFuncion(param) → Crea una nueva función que llama a la original con parámetros
miFuncion(param) → Ejecuta inmediatamente (generalmente ERROR en React)
💡 Ejercicio Mental:
Si vieras esto:
<Accion
accion={saludar}
texto="Saludar"
/>¿Cómo tendría que estar definida saludar?
const saludar = () => {
// ¿Qué pondrías aquí?
};Respuesta: Tendría que ser una función que NO requiera parámetros, por ejemplo:
const saludar = () => {
alert("¡Hola a todos!");
};Componente Padre: AppSaludo.js
function AppSaludo() {
const saludar = (nombre) => {
alert(`Hola ${nombre}`);
};
return (
<div>
<Accion
accion={() => saludar("Mundo")}
texto="Saludar"
/>
</div>
);
}Componente Hijo: Accion.js
function Accion({ accion, texto }) {
return (
<button
onClick={accion}
style={{
padding: "10px 20px",
margin: "10px",
backgroundColor: "green",
color: "white",
border: "none",
borderRadius: "5px"
}}
>
{texto}
</button>
);
}Componente Padre: AppCalculo.js
function AppCalculo() {
const sumar = (a, b) => {
return a + b;
};
const multiplicar = (a, b) => {
return a * b;
};
return (
<div>
<Resultado
calcular={() => sumar(5, 3)}
titulo="Sumar 5 + 3"
/>
<Resultado
calcular={() => sumar(10, 7)}
titulo="Sumar 10 + 7"
/>
</div>
);
}
function AppCalculo() { const sumar = (a, b) => { return a + b; }; const multiplicar = (a, b) => { return a * b; }; return ( <div> <Resultado calcular={() => sumar(5, 3)} titulo="Sumar 5 + 3" /> <Resultado calcular={() => sumar(10, 7)} titulo="Sumar 10 + 7" /> </div> ); }
Componente Hijo: Resultado.js
function Resultado({ calcular, titulo }) {
return (
<div style={{
border: '1px solid orange',
padding: '15px',
margin: '10px',
borderRadius: '8px'
}}>
<h4>{titulo}</h4>
<p>Resultado: {calcular()}</p>
</div>
);
}
function Resultado({ calcular, titulo }) {
return (
<div style={{
border: '1px solid orange',
padding: '15px',
margin: '10px',
borderRadius: '8px'
}}>
<h4>{titulo}</h4>
<p>Resultado: {calcular()}</p>
</div>
);
}**********************************************
Pasar propiedades de hijo a padre en React
En React, el flujo de datos es unidireccional: de padre a hijo. Para pasar datos del hijo al padre, se usa una técnica llamada "lifting state up" (elevar el estado) o pasar callbacks como props.
Concepto básico
El padre pasa una función como prop al hijo, y el hijo llama a esa función con los datos que quiere enviar al padre.
Ejemplo 1: Contador simple
// Componente Padre
import React, { useState } from 'react';
import Hijo from './Hijo';
function Padre() {
const [valorDesdeHijo, setValorDesdeHijo] = useState('');
// Función que recibirá datos del hijo
const manejarDatosDelHijo = (datos) => {
setValorDesdeHijo(datos);
};
return (
<div style={{ padding: '20px', border: '2px solid blue' }}>
<h2>Componente Padre</h2>
<p>Valor recibido del hijo: <strong>{valorDesdeHijo}</strong></p>
{/* Pasamos la función como prop al hijo */}
<Hijo onEnviarDatos={manejarDatosDelHijo} />
</div>
);
}
export default Padre;// Componente Hijo
import React, { useState } from 'react';
function Hijo({ onEnviarDatos }) {
const [inputValue, setInputValue] = useState('');
const manejarCambio = (e) => {
setInputValue(e.target.value);
};
const manejarEnvio = () => {
// Llamamos a la función del padre con los datos
onEnviarDatos(inputValue);
setInputValue('');
};
return (
<div style={{ padding: '15px', border: '1px solid green', marginTop: '10px' }}>
<h3>Componente Hijo</h3>
<input
type="text"
value={inputValue}
onChange={manejarCambio}
placeholder="Escribe algo..."
/>
<button onClick={manejarEnvio}>Enviar al padre</button>
</div>
);
}
export default Hijo;Ejemplo 2: Formulario de tareas
// Componente Padre - Lista de tareas
import React, { useState } from 'react';
import FormularioTarea from './FormularioTarea';
function ListaTareas() {
const [tareas, setTareas] = useState([]);
// Función para agregar nueva tarea desde el hijo
const agregarTarea = (nuevaTarea) => {
setTareas([...tareas, {
id: Date.now(),
texto: nuevaTarea,
completada: false
}]);
};
return (
<div style={{ padding: '20px', maxWidth: '500px' }}>
<h1>Lista de Tareas</h1>
{/* Pasamos la función para agregar tareas */}
<FormularioTarea onAgregarTarea={agregarTarea} />
<h3>Tareas:</h3>
<ul>
{tareas.map(tarea => (
<li key={tarea.id}>
{tarea.texto}
{tarea.completada && ' ✓'}
</li>
))}
</ul>
</div>
);
}
export default ListaTareas;// Componente Hijo - Formulario de tarea
import React, { useState } from 'react';
function FormularioTarea({ onAgregarTarea }) {
const [textoTarea, setTextoTarea] = useState('');
const manejarSubmit = (e) => {
e.preventDefault();
if (textoTarea.trim() === '') return;
// Enviamos la nueva tarea al padre
onAgregarTarea(textoTarea);
setTextoTarea('');
};
return (
<form onSubmit={manejarSubmit} style={{ marginBottom: '20px' }}>
<input
type="text"
value={textoTarea}
onChange={(e) => setTextoTarea(e.target.value)}
placeholder="Nueva tarea..."
style={{ padding: '8px', marginRight: '10px' }}
/>
<button type="submit">Agregar Tarea</button>
</form>
);
}
export default FormularioTarea;Ejemplo 3: Componente de calificación
// Componente Padre - Aplicación de reseñas
import React, { useState } from 'react';
import SelectorCalificacion from './SelectorCalificacion';
function AppReseñas() {
const [calificacion, setCalificacion] = useState(0);
const [reseñas, setReseñas] = useState([]);
// Función para manejar la calificación del hijo
const manejarCalificacion = (valor, comentario) => {
setCalificacion(valor);
// Agregar a la lista de reseñas
setReseñas([
...reseñas,
{ valor, comentario, fecha: new Date().toLocaleDateString() }
]);
};
return (
<div style={{ padding: '20px', fontFamily: 'Arial' }}>
<h1>Sistema de Reseñas</h1>
<p>Calificación actual: {calificacion}/5</p>
{/* Pasamos la función al hijo */}
<SelectorCalificacion onCalificar={manejarCalificacion} />
<h3>Reseñas anteriores:</h3>
{reseñas.length === 0 ? (
<p>No hay reseñas aún</p>
) : (
<ul>
{reseñas.map((reseña, index) => (
<li key={index}>
<strong>{reseña.valor}/5</strong> - {reseña.comentario}
<span style={{ color: 'gray', fontSize: '0.8em', marginLeft: '10px' }}>
({reseña.fecha})
</span>
</li>
))}
</ul>
)}
</div>
);
}
export default AppReseñas;// Componente Hijo - Selector de calificación
import React, { useState } from 'react';
function SelectorCalificacion({ onCalificar }) {
const [calificacionSeleccionada, setCalificacionSeleccionada] = useState(0);
const [comentario, setComentario] = useState('');
const manejarClickEstrella = (valor) => {
setCalificacionSeleccionada(valor);
};
const manejarEnvio = () => {
if (calificacionSeleccionada === 0) {
alert('Por favor, selecciona una calificación');
return;
}
// Enviamos la calificación y comentario al padre
onCalificar(calificacionSeleccionada, comentario);
setComentario('');
};
return (
<div style={{ padding: '15px', border: '1px solid #ddd', borderRadius: '5px' }}>
<h3>Califica nuestro servicio:</h3>
<div style={{ marginBottom: '10px' }}>
{[1, 2, 3, 4, 5].map((estrella) => (
<button
key={estrella}
onClick={() => manejarClickEstrella(estrella)}
style={{
fontSize: '24px',
background: 'none',
border: 'none',
cursor: 'pointer',
color: estrella <= calificacionSeleccionada ? 'gold' : 'lightgray'
}}
>
{estrella <= calificacionSeleccionada ? '★' : '☆'}
</button>
))}
<span style={{ marginLeft: '10px' }}>{calificacionSeleccionada}/5</span>
</div>
<textarea
value={comentario}
onChange={(e) => setComentario(e.target.value)}
placeholder="Comentario opcional..."
style={{ width: '100%', padding: '8px', marginBottom: '10px' }}
/>
<button onClick={manejarEnvio} style={{ padding: '8px 16px' }}>
Enviar Calificación
</button>
</div>
);
}
export default SelectorCalificacion;Resumen de la técnica
En el componente padre: Define una función que manejará los datos recibidos del hijo.
Pasa la función como prop al componente hijo.
En el componente hijo: Recibe la función como prop y la llama cuando necesite enviar datos al padre.
El hijo pasa los datos como argumento(s) de la función.
Ventajas de este patrón
Mantiene el flujo de datos predecible
Centraliza el estado en el componente padre
Facilita la comunicación entre componentes hermanos (a través del padre común)
Hace los componentes hijos más reutilizables
Este patrón es fundamental en React y se usa constantemente en aplicaciones reales.
Comentarios
Publicar un comentario