Nuevo concepto: Controles
El termino Controles se utiliza para llamar de forma genérica a los elementos que conforman un formulario y que el usuario puede interactuar con ellos, por ejemplo: input, radio button, checkbox, select, textarea, etc.
Los formularios son una parte fundamental de cualquier aplicación, pues son la puerta de entrada para que los usuarios puedan interactuar con la aplicación, y en React no es la excepción. Sin embargo, existe una diferencia sustancia al trabajar con formularios en React y en una tecnología web convencional, ya que React almacena la información en sus Estados, y no en una sesión del lado del servidor, como sería el caso de una aplicación web tradicional.
En React existe dos formas de administrar los controles de un formulario, controlados y no controlados, el primero permite ligar el valor de un campo al estado, mientras que el segundo permite tener un campo de libre captura, el cual no está ligado al estado o una propiedad.
Nuevo concepto: Controles
El termino Controles se utiliza para llamar de forma genérica a los elementos que conforman un formulario y que el usuario puede interactuar con ellos, por ejemplo: input, radio button, checkbox, select, textarea, etc.
Los componentes controlados son todos aquellos que su valor está ligado directamente al estado del componente o una propiedad (prop), lo que significa que el control siempre mostrará el valor del objeto asociado.
Para que un control sea considerado controlador (Controlled), es necesario vincular su valor con el estado o una propiedad mediante el atributo value, como podemos ver en el siguiente ejemplo.
1<input type="text" value={this.state.field} />
Debido a que el valor mostrado es una representación del estado o propiedad, el usuario no podrá editar el valor del control directamente. Veamos un ejemplo para comprender esto. Crearemos un nuevo archivo llamado FormTest.js
y lo dejaremos de la siguiente forma:
1import React from 'react'
2import Image from 'next/image'
3
4class FormTest extends React.Component{
5
6 constructor(props){
7 super(props)
8 this.state = {
9 field: "Init values"
10 }
11 }
12
13 render(){
14
15 return (
16 <input type="text" value={this.state.field} />
17 )
18 }
19}
20export default FormTest
A continuación, modificaremos el archivo App.js para mostrar el componente FormTest
en el método render
. No olvidemos importar el componente:
1render(){
2 return (
3 <FormTest/>
4 )
5 }
Finalmente, guardamos los cambios y actualizamos el navegador para reflejar los cambios:
Una vez actualizado el navegador, podremos ver el campo de texto con el valor que pusimos en el estado del componente, y si intentamos actualizar el valor, veremos que este simplemente no cambiará. Esto es debido a que React muestra el valor como inmutable.
Observemos en la imagen que React nos ha arrojado un warning, esta advertencia se debe a que un campo controlado, deberá definir el atributo onChange
para controlar los cambios en el control, de lo contrario, este campo será de solo lectura.
Para solucionar este problema, deberemos de crear una función que tome los cambios en el control y posteriormente actualice el estado con el nuevo valor. Cuando React detecte el cambio en el estado, iniciará la actualización de la vista y los cambios será reflejados. Veamos cómo implementar esta función:
1import React from 'react'
2import Image from 'next/image'
3import update from 'immutability-helper'
4
5class FormTest extends React.Component{
6
7 constructor(props){
8 super(props)
9 this.state = {
10 field: "Init values"
11 }
12 }
13
14 updateField(e){
15 this.setState(update(this.state, {
16 field: {$set: e.target.value}
17 }))
18 }
19
20 render(){
21 return (
22 <input type="text" value={this.state.field}
23 onChange={this.updateField.bind(this)}/>
24 )
25 }
26}
27export default FormTest
Lo primero será definir el atributo onChange
y asignarle la función updateField
. Con esto, cuando se presione una tecla sobre el control, este lanzará un evento que será tratado por esta función. Cuando la función reciba el evento de cambio, actualizará el estado (línea 14) y React automáticamente actualizará la vista, cuando esto pase, el campo tomará el nuevo valor del estado.
Todos los controles funcionan exactamente igual que en HTML tradicional, sin embargo, existe dos controles que se utilizan de forma diferente, los cuales son los TextArea
y Select
. Analicémoslo por separado.
La forma tradicional de utilizar un TextArea
es poner el valor entre la etiqueta de apertura y cierre, como se ve en el siguiente ejemplo:
1<textarea>{this.state.field}</textarea>
En React, para definir el valor de un TextArea
se deberá utilizar el atributo value, como podemos ver en el siguiente ejemplo:
1<textarea value={this.state.field}/>
El control Select
cambia solo la forma en que seleccionamos el valor por default, pues en HTML tradicional solo deberemos utilizar el atributo selected sobre el valor por default, veamos un ejemplo:
1<select>
2 <option value="volvo">Volvo</option>
3 <option value="saab">Saab</option>
4 <option value="vw">VW</option>
5 <option value="audi" selected>Audi</option>
6</select>
En React, cambiamos el atributo selected sobre la etiqueta option, por el atributo value
sobre la etiqueta select, el cual deberá coincidir con el value del option, veamos un ejemplo:
1<select value="audi">
2 <option value="volvo">Volvo</option>
3 <option value="saab">Saab</option>
4 <option value="vw">VW</option>
5 <option value="audi">Audi</option>
6</select>
Los componentes no controlados son aquellos que no están ligados al estado o propiedades. Por lo general deberemos evitar utilizar controles no controlados, pues se sale del principio de React, aunque esto no significa que no debamos utilizarlos nunca, pues existen escenarios concretos en donde pueden resultar útiles, como lo son formularios grandes, donde no requerimos realizar acción alguna hasta que se manda el formulario.
Para crear un componente no controlado, están simple como definir el control sin el atributo value
. Al no definir este atributo, React sabrá que el valor de este control es libre y permitirá su edición sin necesidad de crear una función que controle los cambios en el control. Para analizar esto, modifiquemos el método render
del componente FormTest
para que quede de la siguiente manera.
1render(){
2 return (
3 <div>
4 <input type="text" value={this.state.field}
5 onChange={this.updateField.bind(this)}/>
6 <br/>
7 <input type="text" name="field2" defaultValue="Init Value 2" />
8 </div>
9 )
10}
Otro de las peculiaridades de React es que ofrece el atributo defaultValue
para establecer un valor por default, y así poder inicializar el control con un texto desde el comienzo. También será necesario utilizar el atributo name
, pues será la forma en que podremos recuperar el valor del campo al momento de procesar el envío.
Una vez aplicados los cambios, actualizamos el valor del control y presionamos el botón submit para que nos arroje en pantalla el valor capturado
Ahora bien, si lo que queremos hacer es recuperar los valores del control al momento de mandar el formulario, deberemos encapsular los controles dentro de un form. Regresemos al archivo FormTest
y actualicemos la función render
para que sea de la siguiente manera:
1render(){
2 return (
3 <div>
4 <input type="text" value={this.state.field}
5 onChange={this.updateField.bind(this)}/>
6 <br/>
7 <form onSubmit={this.submitForm.bind(this)} >
8 <input type="text" name="field2" />
9 <br/>
10 <button type="submit">Submit</button>
11 </form>
12 </div>
13 )
14}
Adicional, agregaremos la función submitForm:
1submitForm(e){
2 alert(this.state.field)
3 alert(e.target.field2.value)
4 e.preventDefault();
5}
Existen dos variantes para recuperar los valores de un control. Si está controlado, solo tendremos que hacer referencia a la propiedad del estado al que está ligado el campo (línea 2), por otra parte, si el campo no es controlado, entonces deberemos recuperar el valor del campo mediante su tributo name, como lo vemos en la línea 3.
preventDefault function
La función e.preventDefault previene que el navegador mande el formulario al servidor, lo que provocaría que el navegador se actualice y nos haga un reset del estado del componente.
Debido a que React trabajo por lo general con AJAX, es importante impedir que el navegador actualice la página, pues esto provocaría que los compontes sean cargados de nuevo y nos borre los estados. Es por eso la importancia de utilizar la función preventDefault.
Todo lo que acabas de ver en este artículo es solo una pequeña parte del libro Aplicaciones reactivas con React, NodeJS & MongoDB, El libro más completo en español para aprender a crear aplicaciones web completas con las tecnologías más potentes de la actualidad, desde el Frontend con React, hasta el Backend con un poderoso API REST con NodeJS y Express y persistiendo todo en MongoDB. te invito a que veas mi libro:
Ver libro© 2021, Copyright - Oscar Blancarte. All rights reserved.