1. Método Básico: Callback Function

 Te explico cómo pasar datos del hijo al padre en React. Hay varias formas, pero la más común es mediante funciones callback.

1. Método Básico: Callback Function

Padre Component

jsx
import React, { useState } from 'react';
import Hijo from './Hijo';

function Padre() {
  const [datoDelHijo, setDatoDelHijo] = useState('');

  // Función que recibe datos del hijo
  const manejarDatoDelHijo = (dato) => {
    setDatoDelHijo(dato);
    console.log('Dato recibido del hijo:', dato);
  };

  return (
    <div>
      <h1>Padre</h1>
      <p>Dato del hijo: {datoDelHijo}</p>
      {/* Paso la función como prop al hijo */}
      <Hijo enviarDatoAlPadre={manejarDatoDelHijo} />
    </div>
  );
}

Hijo Component

jsx
import React, { useState } from 'react';

function Hijo({ enviarDatoAlPadre }) {
  const [inputValue, setInputValue] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    // Llamo a la función del padre con los datos
    enviarDatoAlPadre(inputValue);
    setInputValue('');
  };

  return (
    <div>
      <h2>Hijo</h2>
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          value={inputValue}
          onChange={(e) => setInputValue(e.target.value)}
          placeholder="Escribe algo"
        />
        <button type="submit">Enviar al padre</button>
      </form>
    </div>
  );
}

2. Ejemplo Práctico Completo

Aquí te muestro un ejemplo más realista:

jsx
// App.js (Padre)
function App() {
  const [listaTareas, setListaTareas] = useState([]);

  const agregarTarea = (nuevaTarea) => {
    setListaTareas([...listaTareas, {
      id: Date.now(),
      texto: nuevaTarea,
      completada: false
    }]);
  };

  return (
    <div className="App">
      <h1>Lista de Tareas</h1>
      <FormularioTarea onAgregarTarea={agregarTarea} />
      <ListaTareas tareas={listaTareas} />
    </div>
  );
}

// FormularioTarea.js (Hijo)
function FormularioTarea({ onAgregarTarea }) {
  const [tarea, setTarea] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    if (tarea.trim()) {
      onAgregarTarea(tarea); // ← Paso datos al padre
      setTarea('');
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        value={tarea}
        onChange={(e) => setTarea(e.target.value)}
        placeholder="Nueva tarea"
      />
      <button type="submit">Agregar</button>
    </form>
  );
}

3. Paso de Múltiples Datos

jsx
// Hijo
function FormularioUsuario({ onSubmit }) {
  const [usuario, setUsuario] = useState({
    nombre: '',
    email: '',
    edad: ''
  });

  const handleSubmit = (e) => {
    e.preventDefault();
    // Paso un objeto con múltiples datos
    onSubmit(usuario);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input 
        value={usuario.nombre}
        onChange={(e) => setUsuario({...usuario, nombre: e.target.value})}
      />
      {/* ... otros campos */}
    </form>
  );
}

// Padre
function App() {
  const manejarNuevoUsuario = (usuarioData) => {
    console.log('Usuario recibido:', usuarioData);
    // nombre, email, edad disponibles aquí
  };

  return <FormularioUsuario onSubmit={manejarNuevoUsuario} />;
}

4. Patrones Avanzados

a) Usando Context API (para evitar prop drilling)

jsx
// Crear contexto
const DataContext = React.createContext();

// Proveedor en el padre
function Padre() {
  const [data, setData] = useState(null);
  
  return (
    <DataContext.Provider value={{ data, setData }}>
      <Hijo />
    </DataContext.Provider>
  );
}

// Hijo consume y actualiza
function Hijo() {
  const { setData } = useContext(DataContext);
  
  const enviarDato = () => {
    setData('Dato del hijo');
  };
  
  return <button onClick={enviarDato}>Enviar</button>;
}

b) Usando useImperativeHandle (menos común)

jsx
// Hijo con forwardRef
const Hijo = forwardRef((props, ref) => {
  const [dato, setDato] = useState('');
  
  useImperativeHandle(ref, () => ({
    getDato: () => dato
  }));
  
  return <input value={dato} onChange={e => setDato(e.target.value)} />;
});

// Padre
function Padre() {
  const hijoRef = useRef();
  
  const obtenerDato = () => {
    const dato = hijoRef.current.getDato();
    console.log(dato);
  };
  
  return (
    <>
      <Hijo ref={hijoRef} />
      <button onClick={obtenerDato}>Obtener dato</button>
    </>
  );
}

5. Buenas Prácticas

  1. Nombres descriptivos: Usa nombres como onSubmitonSaveonUpdate

  2. Props de sólo lectura: El hijo no debería modificar props directamente

  3. Validación de props: Usa PropTypes o TypeScript

  4. Lifting state up: Si varios hijos necesitan compartir estado, súbelo al ancestro común más cercano

Resumen

La forma más común y recomendada es:

  1. Padre: Define una función que maneje los datos

  2. Padre: Pasa esa función como prop al hijo

  3. Hijo: Llama a la función prop con los datos como argumento

  4. Padre: Recibe y procesa los datos

Este patrón mantiene un flujo de datos unidireccional y predecible, que es una de las fortalezas de React.

Comentarios

Entradas más populares de este blog

1-Sistema de Tareas en React

0-Gestión de estado en una aplicación de tareas

2-Agregar una Tarea a tu Lista de Tareas en React