12 - Formularios: enlace de controles con variables de estados (Hooks de estados)

Cuando trabajamos con formulario HTML los controles almacenan el valor cargado. Con React es muy común enlazar cada control de formulario con una o más variables de estado mediante el empleo de Hook.

Este enlace nos facilita implementar validaciones de ingreso de datos inmediatamente después que el operador los carga.

Problema

Confeccionar un formulario HTML que solicite la carga del nombre, edad y si tiene estudios o no una persona. Utilizar controles:

<input type="text"  />
<input type="number" />
<input type="checkbox" />

Almacenar en una variable de estado de la componente cada vez que ocurre un cambio en un control de formulario. Mostrar en todo momento que datos están almacenado en la variable de estado.

Crear con la aplicación create-react-app el proyecto012

La interfaz visual debe ser:

formularios react

App.js

import { useState } from 'react';

function App() {

  const [datos, setDatos] = useState({
    nombre: '',
    edad: '',
    estudios: false
  })

  function cambioNombre(e) {
    setDatos((valores) => ({
      ...valores,
      nombre: e.target.value,
    }))
  }

  function cambioEdad(e) {
    setDatos((valores) => ({
      ...valores,
      edad: e.target.value,
    }))
  }

  function cambioEstudio(e) {
    setDatos((valores) => ({
      ...valores,
      estudios: !datos.estudios,
    }))
  }

  function procesar(e) {
    e.preventDefault();
    alert('Dato cargado ' + datos.nombre + ' ' 
      +datos.edad + ' ' 
      +datos.estudios);
  }

  return (
    <div>
      <form onSubmit={procesar}>
        <p>Ingrese nombre:<input type="text" value={datos.nombre} onChange={cambioNombre} /></p>
        <p>Ingrese edad:<input type="number" value={datos.edad} onChange={cambioEdad} /></p>
        <p>Estudios:<input type="checkbox" value={datos.estudios} onChange={cambioEstudio} /></p>
        <p><input type="submit" /></p>
      </form>
      <hr />
      <h3>Datos Ingresados</h3>
      <p>Nombre:{datos.nombre}</p>
      <p>Edad:{datos.edad}</p>
      <p>Estudios:{datos.estudios ? 'con estudios' : 'sin estudios'}</p>
    </div>
  );
}

export default App;

Definimos un Hook de estado con un objeto con tres atributos que almacenarán los valores ingresados en el formulario:

  const [datos, setDatos] = useState({
    nombre: '',
    edad: '',
    estudios: false
  })

En el bloque JSX mostramos los datos actuales de la variable de estado asignando a la propiedad value el valor almacenado en cada atributo del objeto:

  return (
    <div>
      <form onSubmit={procesar}>
        <p>Ingrese nombre:<input type="text" value={datos.nombre} onChange={cambioNombre} /></p>
        <p>Ingrese edad:<input type="number" value={datos.edad} onChange={cambioEdad} /></p>
        <p>Estudios:<input type="checkbox" value={datos.estudios} onChange={cambioEstudios} /></p>
        <p><input type="submit" /></p>
      </form>
      <hr />

También definimos para cada evento onChange un método que sincronizará el control con el 'estado'.

Mostramos los valores almacenados en todo momento en la variable de estado:

      <h3>Datos Ingresados</h3>
      <p>Nombre:{datos.nombre}</p>
      <p>Edad:{datos.edad}</p>
      <p>Estudios:{datos.estudios ? 'con estudios' : 'sin estudios'}</p>
    </div>
  );

En las funciones cambioNombre, cambioEdad y cambioEstudio actualizamos el estado respectivo llamando a la función setDatos (recordemos que esto hace que se actualice la página solo en aquellos lugares que lo necesiten):

  function cambioNombre(e) {
    setDatos((valores) => ({
      ...valores,
      nombre: e.target.value,
    }))
  }

  function cambioEdad(e) {
    setDatos((valores) => ({
      ...valores,
      edad: e.target.value,
    }))
  }

  function cambioEstudio(e) {
    setDatos((valores) => ({
      ...valores,
      estudios: !datos.estudios,
    }))
  }

Cuando se presiona el botón submit mediante un alert mostramos los datos cargados en la variable de estado:

  function procesar(e) {
    e.preventDefault();
    alert('Dato cargado ' + datos.nombre + ' ' 
      +datos.edad + ' ' 
      +datos.estudios);
  }