En la parte de hoy de la traducción del curso React, le sugerimos que complete la próxima tarea práctica y presente a su atención una historia sobre cómo modificar el estado de los componentes React.

→
Parte 1: descripción general del curso, razones de la popularidad de React, ReactDOM y JSX→
Parte 2: componentes funcionales→
Parte 3: archivos de componentes, estructura del proyecto→
Parte 4: componentes principales y secundarios→
Parte 5: inicio del trabajo en una aplicación TODO, los fundamentos del estilo→
Parte 6: sobre algunas características del curso, JSX y JavaScript→
Parte 7: estilos en línea→
Parte 8: trabajo continuo en la aplicación TODO, familiaridad con las propiedades de los componentes→
Parte 9: propiedades del componente→
Parte 10: Taller sobre trabajo con propiedades de componentes y estilo→
Parte 11: generación de marcado dinámico y método de matrices de mapas→
Parte 12: taller, tercera etapa de trabajo en una aplicación TODO→
Parte 13: componentes basados en clases→
Parte 14: taller sobre componentes basados en la clase, estado de los componentes.→
Parte 15: talleres de componentes de salud→
Parte 16: la cuarta etapa de trabajo en una aplicación TODO, manejo de eventos→
Parte 17: quinta etapa de trabajo en una aplicación TODO, modificando el estado de los componentes→
Parte 18: la sexta etapa de trabajo en una aplicación TODO→
Parte 19: métodos del ciclo de vida de los componentes.Parte 20: la primera lección de representación condicional→
Parte 21: segunda lección y taller sobre representación condicional→
Parte 22: la séptima etapa de trabajo en una aplicación TODO, descargando datos de fuentes externas→
Parte 23: primera lección sobre trabajar con formularios→
Parte 24: Segunda lección de formularios→
Parte 25: Taller sobre trabajo con formularios→
Parte 26: arquitectura de la aplicación, patrón de contenedor / componente→
Parte 27: proyecto del cursoLección 31. Taller. TODO aplicación. Etapa número 5
→
Original▍Trabajo
Al iniciar nuestra aplicación Todo, puede notar que se muestra una notificación en la consola que indica que nosotros, después de haber configurado la propiedad
checked
de un elemento en el componente
TodoItem
, no proporcionamos un mecanismo para interactuar con este elemento en forma de un
onChange
eventos
onChange
. Al trabajar con la interfaz de la aplicación, esto da como resultado el hecho de que los indicadores que se muestran en la página no se pueden marcar ni desmarcar.
Aquí está invitado a equipar un elemento del tipo de
checkbox
de
checkbox
del componente
TodoItem
con un controlador de eventos
TodoItem
, que, en esta etapa del trabajo, es suficiente presentarlo como una función que genera algo en la consola.
▍Solución
TodoItem
es como se ve el código del componente
TodoItem
ahora, que se almacena en el archivo
TodoItem.js
:
import React from "react" function TodoItem(props) { return ( <div className="todo-item"> <input type="checkbox" checked={props.item.completed}/> <p>{props.item.text}</p> </div> ) } export default TodoItem
Esto es lo que muestra la consola cuando se inicia la aplicación.
Notificación de consolaAl mismo tiempo, las banderas no responden a nuestros efectos.
Para deshacerse de esta notificación y preparar el proyecto para futuros trabajos, es suficiente asignar un
onChange
eventos
onChange
al elemento de
checkbox
. Así es como se ve en el código:
import React from "react" function TodoItem(props) { return ( <div className="todo-item"> <input type="checkbox" checked={props.item.completed} onChange={() => console.log("Changed!")} /> <p>{props.item.text}</p> </div> ) } export default TodoItem
¡Aquí, como manejador, usamos una función simple que genera la palabra
Checked!
en la consola
Checked!
. Al mismo tiempo, al hacer clic en las banderas no se produce un cambio en su estado, pero la notificación de la consola, como se puede ver en la siguiente figura, desaparece.
Las banderas aún no funcionan, pero las notificaciones de la consola desaparecieronEste pequeño cambio realizado en la aplicación nos permitirá, después de tratar el cambio en el estado de los componentes, hacer que las casillas de verificación funcionen correctamente.
Lección 32. Cambio del estado de los componentes
→
OriginalComencemos con una aplicación estándar creada usando
create-react-app
, en el archivo
App.js
que contiene el siguiente código:
import React from "react" class App extends React.Component { constructor() { super() this.state = { count: 0 } } render() { return ( <div> <h1>{this.state.count}</h1> <button>Change!</button> </div> ) } } export default App
El
index.css
estilos
index.css
, que se
index.js
en el archivo
index.js
, contiene la siguiente descripción de estilos:
div { display: flex; flex-direction: column; align-items: center; justify-content: center; } h1 { font-size: 3em; } button { border: 1px solid lightgray; background-color: transparent; padding: 10px; border-radius: 4px; } button:hover { cursor: pointer; } button:focus { outline:0; }
En esta etapa, la aplicación se parece a la que se muestra en la siguiente figura.
Página de aplicación en el navegadorHoy hablaremos sobre cómo cambiar el estado de los componentes. Si el componente tiene un estado, esto permite, inicializándolo, almacenar algunos datos en él. Pero si no se pudiera cambiar el estado, entonces el componente no se beneficiaría mucho de su presencia, almacenar los datos en él no sería muy diferente de, por ejemplo, copiarlos en el código del componente.
Hablemos de la aplicación, en cuyo ejemplo consideraremos trabajar con el estado del componente. El componente de la
App
cuyo código se presenta arriba es un componente basado en clases. Esto es bastante obvio, ya que necesitamos que este componente tenga un estado. En el código del componente, usamos el constructor.
En él, como siempre, llamamos al método
super()
e inicializamos el estado escribiendo la propiedad de
count
y asignándole un valor inicial de
0
. En el método
render()
, imprimimos un encabezado de primer nivel que representa el valor de la propiedad
count
del estado del componente, así como un botón con la palabra
Change!
. Todo esto está formateado con estilos.
Si, en esta etapa del trabajo en la aplicación, ábrala en un navegador y haga clic en el botón, entonces, por supuesto, no pasará nada. Pero debemos hacer clic en el botón para cambiar el estado del componente, lo que afecta su propiedad de
count
. Al mismo tiempo, ya hemos estudiado la metodología para manejar eventos en React, y nuestra tarea es crear un mecanismo que, respondiendo a un clic en un botón, cambie la propiedad de estado del
count
.
Comencemos a resolver nuestra tarea equipando el botón con un
onClick
eventos
onClick
, que, para empezar, simplemente generará algo en la consola.
Para hacer esto, agregaremos un nuevo método a la clase de componente. Puede llamarlo como desee, pero es habitual llamar a tales métodos para que sus nombres indiquen los eventos que están procesando. Como resultado, nosotros, ya que lo vamos a usar para procesar el evento
click
, lo llamamos
handleClick()
. Así es como se verá el código del componente de la
App
.
import React from "react" class App extends React.Component { constructor() { super() this.state = { count: 0 } } handleClick() { console.log("I'm working!") } render() { return ( <div> <h1>{this.state.count}</h1> <button onClick={this.handleClick}>Change!</button> </div> ) } } export default App
Tenga en cuenta que haciendo referencia a este método desde
render()
, utilizamos una construcción del formulario
this.handleClick
.
Ahora, si hace clic en el botón, el mensaje correspondiente aparecerá en la consola.
Al hacer clic en el botón se llama al método de clase.Ahora hagamos que al hacer clic en el botón aumente el número que se muestra arriba, es decir, modificar el estado del componente. ¿Quizás intente cambiar el estado del componente directamente, en el método
handleClick()
? Digamos que si reescribimos este método así:
handleClick() { this.state.count++ }
Debo decir de inmediato que esto no funciona con el estado de los componentes en React. Intentar ejecutar dicho código arrojará un error.
La condición del componente se puede comparar con la ropa que usa una persona. Si quiere cambiarse de ropa, entonces no se cambia ni repinta la ropa sin quitarse la ropa, sino que se la quita y se pone algo más. De hecho, así es exactamente cómo funcionan con el estado de los componentes.
Puede recordar que hablamos sobre un método especial utilizado para modificar el estado, disponible en componentes basados en clases debido al hecho de que extienden la clase
React.Component
. Este es el método
setState()
. Se utiliza en casos en los que necesita cambiar el estado de un componente. Este método puede usarse de diferentes maneras.
Recordemos que un estado es un objeto. Intentemos pasar al método
setState()
un objeto que reemplazará el estado. Reescribimos el método
handleClick()
esta manera:
handleClick() { this.setState({ count: 1 }) }
Intentar usar este método causará el siguiente error:
TypeError: Cannot read property 'setState' of undefined
. De hecho, de lo que estamos hablando ahora está causando mucha controversia entre los desarrolladores de React, y ahora les voy a mostrar una forma muy simple de resolver este problema, que, a primera vista, puede parecer inusual.
El punto es que cada vez, al crear un método de clase (
handleClick()
en nuestro caso), en el que se planea usar el método
setState()
, este método debe estar asociado con
this
. Esto se hace en el constructor. El código del componente después de esta modificación se verá así:
import React from "react" class App extends React.Component { constructor() { super() this.state = { count: 0 } this.handleClick = this.handleClick.bind(this) } handleClick() { this.setState({ count: 1 }) } render() { return ( <div> <h1>{this.state.count}</h1> <button onClick={this.handleClick}>Change!</button> </div> ) } } export default App
¡Ahora después de hacer clic en el botón
Change!
el número 1 aparecerá encima, no se mostrarán mensajes de error.
Al presionar un botón se modifica el estadoEs cierto que el botón resultó ser "de una sola vez". Después del primer clic,
0
cambia a
1
y, si vuelve a hacer clic, no pasará nada. En general, esto no es sorprendente. El código que se llama cuando se hace clic en el botón hace su trabajo, cada vez que cambia el estado a uno nuevo, sin embargo, después del primer clic en el botón, el nuevo estado en el que se almacena el número
1
en la propiedad de
count
no diferirá del anterior. Para resolver este problema, considere otra forma de trabajar con el método
setState()
.
Si no estamos interesados en cuál era el estado anterior del componente, simplemente podemos pasar un objeto a este método, que reemplazará el estado. Pero a menudo sucede que el nuevo estado de un componente depende del anterior. En nuestro caso, esto significa que, en función del valor de la propiedad
count
, que se almacena en la versión anterior del estado, queremos agregar 1 a este valor. En los casos en los que para cambiar el estado, debe tener en cuenta lo que se almacenó previamente en él, puede pasar al método
setState()
una función que, como parámetro, recibe la versión anterior del estado. Puede nombrar este parámetro como desee, en nuestro caso será
prevState
. La adquisición de esta función se verá así:
handleClick() { this.setState(prevState => { }) }
Puede pensar que en tal función es suficiente simplemente referirse al estado utilizando una construcción de la forma
this.state
, pero este enfoque no nos conviene. Por lo tanto, es importante que esta función acepte la versión anterior del estado del componente.
La función debería devolver una nueva versión del estado.
handleClick()
se verá el método
handleClick()
para
handleClick()
este problema:
handleClick() { this.setState(prevState => { return { count: prevState.count + 1 } }) }
Tenga en cuenta que para obtener el nuevo valor de la propiedad
count
, utilizamos la construcción
count: prevState.count + 1
. Puede pensar que una construcción del formulario
count: prevState.count++
, pero el operador
++
count: prevState.count++
variable a la que se aplica, esto significará un intento de modificar la versión anterior del estado, por lo que no la usamos aquí.
El código completo del archivo componente en esta etapa se verá así:
import React from "react" class App extends React.Component { constructor() { super() this.state = { count: 0 } this.handleClick = this.handleClick.bind(this) } handleClick() { this.setState(prevState => { return { count: prevState.count + 1 } }) } render() { return ( <div> <h1>{this.state.count}</h1> <button onClick={this.handleClick}>Change!</button> </div> ) } } export default App
Ahora cada clic en el botón aumenta el valor del contador.
Cada clic en el botón aumenta el valor del contador.Lo que acabamos de descubrir nos abre grandes oportunidades en el desarrollo de aplicaciones React.
Dijimos anteriormente que un componente primario puede, a través de un mecanismo de propiedad, pasar propiedades de su propio estado a componentes secundarios. Si React detecta un cambio en el estado del componente primario, volverá a representar el componente secundario al que se pasa este estado. Parece una llamada al método
render()
. Como resultado, el componente secundario reflejará los nuevos datos almacenados en el estado del componente principal.
Resumen
Hoy preparó la aplicación Todo para seguir trabajando en ella y también se familiarizó con los mecanismos utilizados en React para cambiar el estado de un componente. La próxima vez se le pedirá que amplíe las capacidades de la aplicación de capacitación utilizando lo que aprendió hoy.
Estimados lectores! ¿Qué le parece el hecho de que el estado de los componentes en React no se puede cambiar directamente sin utilizar mecanismos especiales?
