Formularios en React: ¿Cómo manejar los formularios en React.js con input controlados y no controlados?

Inicioreact jsFormularios en React
Formularios en React: ¿Cómo manejar los formularios en React.js con input controlados y no controlados?

by Juan Carlos García

3-Mzo-2023

(2)

Suscribirme al canal:

Hola de nuevo viajero, hoy vamos a continuar con este curso de React JS y el tema que tocaremos el día de hoy es referente al Manejo de Formularios en React, este es un tema sumamente importante ya que prácticamente en toda página web vas a necesitar de al menos un formulario.

Cabe aclarar, que en este primer post veremos las formas en que podemos manejar formularios sin ocupar librerías de terceros, si este curso recibe bastante apoyo, iré complementando con algunas librerías que existen y que en algunos casos suelen ser de utilidad.

  • Si aun no has visto el capítulo anterior sobre Listas y condiciones en React, por favor revísalo para que vayas en orden y aprendas cada concepto.

¡No te puedes perder las nuevas clases 🧐!

React JS

React JS

React.js: El mejor curso gratuito de React.js desde cero.

¿Que es React JSX?

¿Que es React JSX?

Guía para principiantes de React JSX: ¿Qué es React JSX? Introducción a React JSX

Componentes y propiedades

Componentes y propiedades

Components and Props React.js, Manejo de propiedades y componentes en React

State y Ciclo de vida en React

State y Ciclo de vida en React

State And Lifecycle: Comprendiendo el State y Ciclo de vida de los componentes en React.js

Refs React

Refs React

¿Qué son las React Refs y para que sirven? Uso de las Refs y manejo del DOM en React.js

Listas y condiciones en React

Listas y condiciones en React

Keys and List: ¿Cómo manejar las listas y condicionales en React JS?

Formularios en React

Formularios en React

Formularios en React: ¿Cómo manejar los formularios en React.js con input controlados y no controlados?

React develepor tools

React develepor tools

React Developer Tools: ¿Cómo analizar el comportamiento y estado de nuestros componentes en React.js?

API Context

API Context

API Context en React: ¿Cómo comunicar componentes mediante API Context en React.js?

Higher Order Component

Higher Order Component

HOC en React.js: ¿Cómo utilizar los High Order Component (HOC) ?

Children en React JS

Children en React JS

Children en React.js: Manejo avanzado de Children en React.js, composición de componentes.

PropTypes en React

PropTypes en React

PropType en React.js: ¿Cómo validar datos a través de PropType en React.js?

Hooks en React JS

Hooks en React JS

Master de Hooks en React JS: ¿Qué es un Hook en React.js? Tipos, funcionamiento y características.

Hook useState

Hook useState

useState: ¿Cómo utilizar el Hook useState en React.js?

Hook useEffect

Hook useEffect

Hook useEffect: ¿Qué es el Hook useEffect? ¿Cómo utilizarlo correctamente y qué reglas seguir?

Hook useContext

Hook useContext

¿Cómo utilizar el Hook useContext? Comunicación de componentes funcionales

Hook useReducer

Hook useReducer

¿Cómo utilizar el Hook useReducer en React.js?

React memo

React memo

Memorizar componentes a través de React.memo en React.js

Hook useCallback

Hook useCallback

Utilizando los Hooks useCallback y useMemo en React.js

🧐 Autoevaluación: Formularios en React

¿Qué son los input no controlados?

¿Qué son los input controlados?

¿Qué aprenderás del manejo de formularios en React JS?

  • Utilización de inputs no controlados a través de refs
  • Recuperar datos de input no controlados a través de eventos
  • Creación de inputs controlados
  • Aprenderás a desarrollar un formulario listo para agregarlo a tu proyecto
  • Conocerás una de las formas en que puedes validar los datos de tu formulario
  • Y mucho más.

Repositorio:

  • Este capitulo lo puedes descargar clonando el repositorio con la siguiente línea de código.
  • Y solo debes cambiarte a la rama de nombre "formularios"
  • Si no estas familiarizado con Git, descarga el código aquí.
  • Recuerda que cada capítulo estará en una rama diferente para llevar un orden

 

git clone https://github.com/EWebik/react-js.git
git checkout formularios

 

Manejo de formularios en React

El comportamiento de formularios en React es un poco diferente a otros elementos dentro del DOM que crea la librería de React, y esto se debe a que los formularios por si mismos almacenan un cierto tipo de estado.

Esto lo podemos ver claramente cuando utilizamos el tag form en HTML el cual tiene uno o mas inputs dentro de su estructura.

Cada input es capaz de almacenar información, por ejemplo, el name o el value, y después, recuperar el value a través de un identificador como el name para enviarlo al servidor a través de una API u otro medio de comunicación que tengamos con nuestro servidor.

 

Componentes controlados y no controlados

En su forma más básica los inputs dentro de un formulario los podemos manejar en una forma:

  • Controlada
  • Y no controlada

 

Inputs no controlados

Los input no controlados son una forma en que podemos manipular los componentes, esto quiere decir, que No vamos a utilizar el state de React para obtener o modificar los valores y propiedades de un form.

Entonces, para utilizar input no controlados lo podemos hacer utilizando:

 

Manejo de Inputs a través de Refs

Esto lo hemos visto en un capítulo anterior y solo debemos crear un referencia y a partir de ello obtener el value del input, por ejemplo:

 

class Componente extends React.Component{

  constructor(props){
    super(props);
    this.nombre = React.createRef();
    this.correo = React.createRef();
  }
  //Inputs no controlados, obteniendo datos a través de Refs
  clicRefs(evento){
    evento.preventDefault();
    console.log(this.nombre.current.value);
    console.log(this.correo.current.value);
  }

  render(){
    return(
      <form>
        <h1>{"Formularios EWebik"}</h1>
        <input type="text" refs={this.nombre} placeholder="Nombre" />
        <input type="text" refs={this.correo} placeholder="Correo" />
        <button onClick={this.clicRefs.bind(this)}>
          Enviar
        </button>
      </form>
    )
  }
}

El código anterior es muy similar a como lo manejamos en HTML, es una buena opción cuando tienes pocos input y no tienes que hacer grandes validaciones.

Manejo de Inputs a través de submit

La forma clásica del manejo de formularios es recuperar la información de cada input cuando se dispara el evento submit, esto seguramente lo has hecho en JavaScript en un login o algo por el estilo, en React lo podemos hacer de la siguiente manera.

class Componente extends React.Component{

  //Inputs no controlados, obteniendo datos a través del evento submit
  clicEventos(evento){
    evento.preventDefault();
    console.log(evento.target[0].value);
    console.log(evento.target[1].value);
  }

  render(){
    return(
      <form onSubmit={this.clicEventos}>
        <h1>{"Formularios EWebik"}</h1>
        <input type="text" placeholder="Nombre" />
        <input type="text" placeholder="Correo" />
        <button>
          Enviar
        </button>
      </form>
    )
  }
}

 

Al igual que en el caso anterior es útil cuando no se tiene que hacer validaciones complejas y son pocos inputs.

 

Ventaja y desventaja de utilizar componentes no controlados

  • Ventaja, el código es menos complejo y muy fácil de escribir.
  • Desventaja, la validación del valor de cada input por lo regular se hace hasta que el usuario lanza el evento submit.

Como puedes ver esta forma de manejo es algo rudimentaria pero es importante que la conozcas, dado que en alguna aplicación quizá te sea útil. Ahora pasemos a los input controlados que es lo que vas a utilizar prácticamente siempre.

 

Inputs controlados

Utilizar los input de una forma controlada es la forma recomendable al utilizar React, ya que que te permitirá reutilizar mucho código y podrás adherir muchas funcionalidades a tus componentes, por ejemplo, desarrollemos el siguiente formulario aplicando componentes controlados.

Formulario ejemplo en el manejo de forms en react js

 

Para pode desarrollar este formulario a través de componentes controlados, debemos crear cada uno de los componentes con su state particular.

 

Creando input tipo text controlado

Este componente utiliza el state para almacenar el valor del input y un estado de error que indicará si el usuario esta introduciendo un dato valido, en formulario de ejemplo lo utilizamos para validar que lo que ingresa es un nombre y un correo, si el código te resulta algo complicado, por favor, mira el vídeo.

class InputText extends React.Component{
  constructor(props){
    super(props);
    this.actualizarState = this.actualizarState.bind(this);
    this.state = {
      value:"",
      error:false,
      mensajeError:""
    };
  }
  actualizarState(e){
    const {name, value} = e.target;
    //console.log(name)
    //console.log(value)
    console.log(this.props.validacion(value));
    
    if(this.props.validacion(value)){
      this.setState({
        value,
        error:false,
        mensajeError:""
      });
      this.props.actualizarState({
        name,value,error:false
      });
    }else{
      this.setState({
        value,
        error:true,
        mensajeError:this.props.mensajeError
      });
      this.props.actualizarState({
        name,value,error:true
      });
    }
  }
  render(){
    return(
      <div className="componente-input">
        <label htmlFor={"id-"+this.props.name}>{this.props.label}</label>
        <input
          id={"id-"+this.props.name}
          type="text"
          name={this.props.name}
          placeholder={this.props.placeholder}
          className={this.state.error ? "border-error":""}
          onChange={this.actualizarState}/>
          {
            this.state.error ? (
            <p className="componente-input-error">{this.state.mensajeError}</p>
            ):("")
          }
      </div>
    )
  }
}

Si el usuario ingresa un dato no valido, se mostrara un párrafo en color rojo que le indica al usuario que el dato no es el correcto y debe corregir.

Creando input tipo Checkbox controlado

Este componente es un poco más simple ya que solo cuenta con dos estados posibles.

class InputCheckbox extends React.Component{
  constructor(props){
    super(props)
    this.actualizarState = this.actualizarState.bind(this);
    this.state={activo:false};
  }
  actualizarState(e){
    const {name, checked} = e.target;
    this.setState({activo:checked});
    this.props.actualizarState({
      name,value:checked,error:false
    })
  }
  render(){
    return(
      <div>
        <input
          id={"id-"+this.props.name}
          type="checkbox"
          name={this.props.name}
          checked={this.state.activo}
          onChange={this.actualizarState}/>
          <label htmlFor={"id-"+this.props.name}>{this.props.label}</label>
      </div>
    )
  }
}

 

Creando input tipo select controlado

Ahora veremos como agregar una lista desplegable de opciones en nuestro formulario, el siguiente checkbox nos permite agregar una lista con las opciones que nosotros deseemos, por el momento solo agregamos dos casos validos y uno no valido, por lo que se valida que el value de la opción no sea un carácter vacío.

 

class InputSelect extends React.Component{
  constructor(props){
    super(props)
    this.actualizarState = this.actualizarState.bind(this);
    this.state={activo:""};
  }
  actualizarState(e){
    const {name, value} = e.target;
    this.setState({value});
    this.props.actualizarState({
      name,value,error: value == "" ? true:false
    })
  }
  render(){
    return(
      <div className="componente-input">
        <label htmlFor={"id-"+this.props.name}>{this.props.label}</label>
        <select
          id={"id-"+this.props.name}
          name={this.props.name}
          onChange={this.actualizarState}>
            {
              this.props.opciones.map((opcion,index)=>(
              <option hey={index} value={opcion.value}>{opcion.texto}</option>
              ))
            }            
        </select>
      </div>
    )
  }
}

 

Creando un form con inputs controlados

Ahora que tenemos nuestros componentes básicos necesitamos crear nuestro formulario agregando cada uno de nuestros inputs controlados y lo haremos de la siguiente manera.

 

 

class Componente extends React.Component{

  constructor(props){
    super(props);
    this.submit = this.submit.bind(this);
    this.actualizarState = this.actualizarState.bind(this);
    this.state = {
      nombre:{
        value:"",
        error:true
      },
      correo:{
        value:"",
        error:true
      },
      prioridad:{
        value:false,
        error:true
      },
      opciones:{
        value:"",
        error:true
      }
    }
  }
  
  actualizarState(input){
    this.setState({
      ...this.state,
      [input.name]:{
        value:input.value,
        error:input.error
      }
    }, ()=>{console.log(this.state);});
    
  }

  submit(e){
    e.preventDefault();
    console.log(this.state)
  }

  render(){
    return(
      <form onSubmit={this.submit}>
        <h1>{"Formularios EWebik"}</h1>
        <InputText
          label="Nombre"
          name="nombre"
          placeholder="Nombre"
          validacion={esNombre}
          mensajeError="Se esperaban letras"
          actualizarState={this.actualizarState} />
        
        <InputText
          label="Correo"
          name="correo"
          placeholder="Correo"
          validacion={esCorreo}
          mensajeError="Correo no valido"
          actualizarState={this.actualizarState} />

        <InputCheckbox
          name="prioridad"
          label="Prioridad"
          actualizarState={this.actualizarState} />

        <InputSelect
          name="opciones"
          label="Elige una opción:"
          actualizarState={this.actualizarState}
          opciones={[
            {value:"", texto:"Seleccione un opción..."},        
            {value:"1", texto:"Página web"},
            {value:"2", texto:"Aplicación móvil"}
            ]} />
        
        <button
          disabled={this.state.nombre.error ||
            this.state.correo.error ||
            this.state.opciones.error}
          type="submit"
          className={this.state.nombre.error ||
            this.state.correo.error ||
            this.state.opciones.error
            ? 
            "button-disable":"button"}>
          Enviar
        </button>
      </form>
    )
  }
}

ReactDOM.render(
  <Componente/>,
  document.getElementById('root')
);

En este componente:

  • Llamamos cada input controlado y lo inicializamos
  • Creamos una validación para cada InputText
  • Tenemos un state que almacena el valor de cada input junto con su estado de error
  • Si un input tiene un error, el botón de envió se mantiene disabled para no enviar datos erroneos
  • Declaramos un función actualizarState la cual recibirá el valor de cada componente del formulario y actualizará el state
  • Por ultimo tenemos una función submit, donde tenemos datos validos y podemos enviarlos a una API o a otro lugar según el tipo de tu aplicación.

Finalmente te dejo el código CSS del formulario, realmente es muy básico y no utilice una paleta de colores, así que puedes modificarlo y mejorarlo antes de utilizarlo en tu proyecto.


.componente-input{
  display: flex;
  flex-direction: column;
  margin: 10px 0px;
}
.componente-input label{
  margin: 5px 0px;
  font-size: 18px;
}
.componente-input input
,.componente-input select{
  height: 45px;
  font-size: 18px;
}
.componente-input-error{
  color: red;
  font-size: 16px;
}
.border-error{
  border: 1px solid red;
}
.button{
  background-color: royalblue;
  padding: 10px;
  font-weight: bold;
  font-size: 18px;
  color: #fff;
}
.button-disable{
  background-color: darkgray;
  padding: 10px;
  font-weight: bold;
  font-size: 18px;
  color: #fff;
}

 

Espero que esta clase te haya sido de gran ayuda, si te ha gustado suscríbete a mi canal de YouTube y comparte para que llegue a más personas que se les dificulta adquirir un corso de React y realmente tengan ganas de aprender, nos vemos en el próximo post.

🧐 Autoevaluación: Formularios en React

¿Qué son los input no controlados?

¿Qué son los input controlados?

Juan Carlos

Juan Carlos García

Desarrollador de software / SEO

Durante años he desarrollado plataformas dedicadas al rastreo satelital y varios sitios web que se encuentran en la primera página de Google, y hoy quiero compartir contigo lo que se en tecnologías como: Node JS, PHP, C# y Bases de datos.

Si quieres apoyarme sígueme en mis redes sociales y suscríbete a mi canal de YouTube.

EWebik

Diseño de páginas web y aplicaciones moviles.

© 2024 EWebik