ReactJS-GeekBook
  • Metodos Funcionales - Profundizando Arreglos de Objetos
  • Programación Orientada a Objetos - Clases en ES6
  • Fundamentos de React
  • Fundamentos de React II
  • Componente en React
  • Eventos en React
  • Estados en React
  • Estados en React II
  • Lifting - Datos de Hijos a Padres
  • Arquitectura de aplicaciones en React
  • Enrutamiento - React Router
  • Ciclo de vida de los Componente en React
  • Debugging de aplicaciones JS y React
  • Testing (Pruebas) en Javascript
Powered by GitBook
On this page
  • Introducción
  • ¿Para qué sirve lo que vamos a ver en esta sesión?
  • Formularios
  • Componentes controlados
  • Refs
  • Usando refs
  • Componentes no controlados: el input de tipo file
  • Recursos externos
  • Documentación de React

Was this helpful?

Estados en React II

Introducción

Los formularios funcionan un poco diferente en React que un formulario simple HTML. Los elementos de formulario almacenan de por sí un estado, que es el valor del input. En React, cuando creamos un formulario vamos a manejar el estado de los input usando el estado de los componentes de React. Manejarlo de esta forma nos va a facilitar procesar los datos introducidos por el usuario, ya sea para hacer validaciones o a la hora de enviar los datos a un servidor.

¿Para qué sirve lo que vamos a ver en esta sesión?

Para crear apps de React que tienen un formulario, y hacerlo de la forma correcta en React. Por ejemplo, ¿no estáis haciendo un proyecto que tiene formularios?

Formularios

Los elementos input de formulario, como bien sabemos, tienen un estado interno: su propiedad value se actualiza cuando el usuario modifica su contenido. En React, además, otros elementos de formulario como textarea y select tienen un comportamiento similar que facilita acceder a estos datos.

Cuando queremos realizar procesamiento de estos datos que introduce el usuario, ya sea para enviar los datos a un API o realizar validaciones, ¿qué hacíamos hasta ahora? Pues teníamos que buscar cada elemento en el DOM y recoger su value. Pero en React sabemos que la información de la interfaz la tenemos en el estado del componente: ¿y si guardamos los datos que introduce el usuario en el estado del componente cada vez que cambia un elemento? Pues es así exactamente como se hace en React.

Partimos de un formulario simple que recoge el nombre del usuario:

class AwesomeForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: ""
    };

    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    this.setState({ name: event.target.value });
  }

  render() {
    return (
      <form>
        <label htmlFor="name">Name:</label>
        <input id="name" type="text" onChange={this.handleChange} />
        <input type="submit" value="Enviar" />
      </form>
    );
  }
}

Hemos creado un componente simple, AwesomeForm, que tiene un formulario con un nombre. Al input de tipo texto para el nombre, le hemos añadido un escuchador de eventos onChange para que cada vez que se modifique el input, se guarde la información en el estado.

NOTA: Fíjate también que en la etiqueta label hemos usado el atributo htmlFor en lugar de for, ya que es una palabra reservada de JavaScript, lo mismo que con pasaba con class y className.

Componentes controlados

Muy bien, pero hay una cosa más que tenemos que hacer para asegurarnos de que la información que guardamos en el estado sea "de verdad verdadera" la que introduce el usuario. Y es obligar a que su value tome los datos directamente del estado, es decir, que se muestren de nuevo en el input.

El ciclo que siguen los datos es:

  1. el usuario escribe en el input

  2. en el evento de cambio se guardan en el estado

  3. al cambiar el estado se ejecuta en método render y se asignan como value al input

¿Y para qué tanto lío? Pues para garantizar que en el estado tenemos todos los datos necesarios para pintar la interfaz. Vamos a ver cómo queda en el ejemplo anterior.

class AwesomeForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: ""
    };

    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    this.setState({ name: event.target.value });
  }

  render() {
    return (
      <form>
        <label htmlFor="name">Name:</label>
        <input
          id="name"
          type="text"
          value={this.state.name}
          onChange={this.handleChange}
        />
        <input type="submit" value="Enviar" />
      </form>
    );
  }
}

A estos elemento de formulario que tienen su value enlazado al estado del componente se les llama componentes controlados (controlled components) y son la forma habitual de manejar campos de formulario en React.

Usar un componente controlado tiene más ventajas, por ejemplo, nos permite validar los datos que introduce el usuario. Como nosotras guardamos los datos en el estado, podemos ejecutar el código que queramos antes de guardarlo y lo que hagamos se verá reflejado en el input puesto que está enlazado al estado a través de su value. Veamos el ejemplo anterior, pero forzando a que el nombre esté en mayúsculas.

    handleChange(event) {
        this.setState({name: event.target.value.toUpperCase()});
    }

EJERCICIO 1

Formulario para pelis

Vamos a crear un formulario en un componente de React que recoja información de una película. Recogeremos información de

  • nombre (en un campo de texto)

  • descripción (en un textarea)

  • género (en un select donde podemos seleccionar comedia, drama o infantil)

Refs

Hasta ahora sabemos que para pintar la información de nuestro componentes en el DOM hemos delegado totalmente en React: nos hemos olvidado de los querySelector y los innerHTML. Para modificar en pantalla los datos de un componente, le paso nuevas props o modifica su estado y se vuelve a pintar actualizado.

Pero para algunos casos concretos vamos a necesitar acceder al DOM directamente y para estos casos React nos ofrece una alternativa: los Refs o referencias al DOM. Debemos usarlos solo en casos muy específicos como:

  • manejar el foco de un elemento de formulario, la selección de texto o la reproducción multimedia

  • iniciar animaciones

  • integrar en nuestra aplicación librerías externas que usan el DOM

Usando refs

Para poder usar refs en nuestro código de React tenemos que seguir estos sencillos pasos:

  1. declarar un atributo en el constructor llamando a la función React.createRef()

  2. crear un atributo ref en el elemento que necesitamos referenciar, y le damos como valor el atributo anterior

  3. para poder usar una referencia al DOM desde un método cualquiera de la clase usamos la propiedad current del atributo declarado en el punto 1

Vamos a ver un ejemplo de la documentación de React que sigue estos 3 pasos para que, al pinchar en un campo, cambiamos el foco a otro campo usando refs.

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    this.textInput = React.createRef();
    this.focusTextInput = this.focusTextInput.bind(this);
  }

  focusTextInput() {
    this.textInput.current.focus();
  }

  render() {
    return (
      <div>
        <input type="text" ref={this.textInput} />

        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

Componentes no controlados: el input de tipo file

Existe una excepción en el uso de elementos de formulario como componentes controlados, y es al usar un campo de tipo fichero (file). En esta caso, no puede ser controlado ya que se trata de un campo de solo lectura porque el único que puede modificarlo, por temas de seguridad, es el usuario de la web.

Para trabajar con este input y, por ejemplo, acceder a su contenido tendremos que acceder a él como un nodo del DOM. Por tanto, vamos a usar las Refs que hemos visto antes para acceder a la información del fichero que ha elegido la usuaria.

Veamos un ejemplo de la documentación de React.

class FileInput extends React.Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.fileInput = React.createRef();
  }
  handleSubmit(event) {
    event.preventDefault();
    alert(`Selected file - ${this.fileInput.current.files[0].name}`);
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Upload file:
          <input type="file" ref={this.fileInput} />
        </label>
        <br />
        <button type="submit">Submit</button>
      </form>
    );
  }
}

EJERCICIO 2

Formulario para pelis II

Partiendo del ejercicio anterior, vamos a añadir un campo más al formulario que sea la carátula de la película. Al elegir el usuario una carátula, se muestra una previsualización de la misma, y se guardan los datos en el estado. Recuerda que para leer la información de ficheros debemos usar un FileReader y para recoger la información de una imagen su método readAsDataURL.

Recursos externos

Documentación de React

Documentación oficial de React (en inglés).

PreviousEstados en ReactNextLifting - Datos de Hijos a Padres

Last updated 5 years ago

Was this helpful?

▸ Usando un componente controlado en Codepen
Formularios en React
Manejo del input tipo file en React
Refs y el DOM