
Hola habrozhiteli! La edición original se lanzó en el otoño de 2017, pero aún se considera el mejor libro para explorar React. El autor actualiza y modifica constantemente el código del libro en el repositorio de
Github .
Sugerimos en una publicación que se familiarice con el pasaje "Estados y su papel en la naturaleza interactiva de React"
Si tuviera que leer solo un capítulo de este libro, ¡debería elegir este! Sin estados, los componentes React no son más que patrones estáticos avanzados. Espero que comparta mi entusiasmo porque comprender los conceptos de este capítulo le permitirá crear aplicaciones mucho más interesantes.
Imagine que está construyendo un campo de entrada con autocompletar (Fig. 4.1). Al ingresar datos, el campo debe emitir una solicitud al servidor para obtener información sobre las opciones adecuadas para mostrar la salida en una página web. Hasta ahora ha trabajado con propiedades y sabe que cambiar las propiedades le permite obtener diferentes vistas. Sin embargo, las propiedades no se pueden cambiar en el contexto del componente actual, ya que se pasan cuando se crea el componente.

En otras palabras, las propiedades son inmutables en el componente actual, lo que significa que no puede cambiar las propiedades en este componente a menos que vuelva a crear el componente y pase los nuevos valores del elemento primario (Fig. 4.2). Pero la información recibida del servidor debe almacenarse en algún lugar, y luego se debe mostrar una nueva lista de opciones en la vista. ¿Cómo actualizar la vista si las propiedades no se pueden cambiar?
Una posible solución es representar un elemento con nuevas propiedades cada vez que reciba una nueva respuesta del servidor. Pero luego debe colocar la lógica fuera del componente, y el componente deja de ser autosuficiente. Obviamente, si los valores de las propiedades no se pueden cambiar, y el autocompletado debería ser autosuficiente, es imposible usar propiedades. Entonces surge la pregunta: ¿cómo actualizar vistas en respuesta a eventos sin volver a crear el componente (createElement () o JSX <NAME />)? Es este problema el que los estados resuelven.
Una vez que la respuesta del servidor está lista, el código de devolución de llamada cambiará el estado del componente en consecuencia. Tendrá que escribir este código usted mismo. Sin embargo, después de actualizar el estado, React actualizará automáticamente la vista por usted (solo en los lugares donde debe actualizarse, es decir, donde se usan los datos del estado).
Con el estado de los componentes React, puede crear aplicaciones interactivas y significativas de React. El estado es un concepto fundamental que le permite crear componentes React que pueden almacenar datos y actualizar vistas automáticamente de acuerdo con los cambios en los datos.
¿Cuál es el estado del componente Reaccionar?
El estado Reaccionar es un almacenamiento de datos de componentes mutables: bloques independientes orientados a funciones de la interfaz de usuario y la lógica. "Variabilidad" significa que los valores de estado pueden cambiar. Usando el estado en la vista (render ()) y cambiando los valores más adelante, puede influir en la apariencia de la vista.
Metáfora: si imagina un componente en forma de función, a la entrada de la cual se transmiten las propiedades y el estado, el resultado de la función será una descripción de la interfaz de usuario (presentación). Las propiedades y los estados expanden las vistas, pero se usan para diferentes propósitos (ver sección 4.3).
Cuando trabaja con estados, accede a ellos por nombre. El nombre es un atributo (es decir, una clave de objeto o una propiedad de objeto, no una propiedad de componente) de este objeto de estado, por ejemplo this.state.autocompleMatches o this.state.inputFieldValue.
Los datos de estado se utilizan a menudo para mostrar información dinámica en una vista para ampliar la representación de las vistas. Volviendo a un ejemplo anterior de un campo de autocompletar: el estado cambia en respuesta a una solicitud XHR al servidor, que, a su vez, se inicia al ingresar datos en el campo. React garantiza que las vistas se actualicen cuando cambie el estado utilizado en las vistas. De hecho, cuando un estado cambia, solo cambian las partes correspondientes de las representaciones (a elementos individuales e incluso a los valores de los atributos de un elemento individual).
Todo lo demás en el DOM permanece sin cambios. Esto es posible gracias al modelo DOM virtual (ver sección 1.1.1), que React utiliza para determinar el delta (totalidad de los cambios) durante el proceso de reconciliación. Este hecho le permite escribir código en un estilo declarativo. React hace toda la rutina por ti. Las etapas principales de cambiar la presentación se discuten en el Capítulo 5.
Los desarrolladores de React usan estados para generar nuevas interfaces de usuario. Las propiedades de componente (this.props), las variables ordinarias (inputValue) y los atributos de clase (this.inputValue) no son adecuados para esto, porque cambiar sus valores (en el contexto del componente actual) no activa un cambio en la vista. Por ejemplo, el siguiente fragmento es antipatrón, lo que muestra que cambiar el valor en cualquier lugar, excepto el estado, no hará que la vista se actualice:
// : ! let inputValue = 'Texas' class Autocomplete extends React.Component { updateValues() ← { ( ) this.props.inputValue = 'California' inputValue = 'California' this.inputValue = 'California' } render() { return ( <div> {this.props.inputValue} {inputValue} {this.inputValue} </div> ) } }
Ahora veamos cómo trabajar con los estados de los componentes React.
Trabajar con estados
Para trabajar con estados, debe poder acceder a los valores, actualizarlos y establecer los valores iniciales. Comencemos refiriéndonos a los estados en los componentes React.
Acceso a los estados
El objeto de estado es un atributo del componente, y debe acceder a él a través del enlace this, por ejemplo this.state.name. Como recordará, se puede acceder a las variables y mostrarlas en código JSX entre llaves ({}). De manera similar, en render (), puede renderizar this.state (como cualquier otra variable o atributo de clase de un componente no estándar), por ejemplo {this.state.inputFieldValue}. Esta sintaxis es similar a la sintaxis para acceder a las propiedades en this.props.name.

Usamos lo que aprendiste para implementar el reloj en la fig. 4.3. Nuestro objetivo es crear una clase de componente autónomo que cualquiera pueda importar y usar en su aplicación sin mucha molestia. El reloj debe mostrar la hora actual.
El proyecto tiene la siguiente estructura:
/clock index.html /jsx script.jsx clock.jsx /js script.js clock.js react.js react-dom.js
Utilizo la CLI de Babel con marcas de seguimiento (-w) y directorio (-d) para compilar todos los archivos fuente JSX desde clock / jsx a la carpeta clock / js de destino y recompilar cuando se detectan cambios. Además, guardé el comando como un script npm en el archivo package.json de la carpeta principal ch04 para ejecutar el comando npm run build-clock desde ch04:
"scripts": { "build-clock": "./node_modules/.bin/babel clock/jsx -d clock/js -w" },
Por supuesto, el tiempo no se detiene (nos guste o no). Debido a esto, debe actualizar constantemente la vista, y para esto puede usar el estado. Denomine currentTime e intente representar el estado como se muestra en el Listado 4.1.
Listado 4.1. Procesamiento de estado JSX
class Clock extends React.Component { render() { return <div>{this.state.currentTime}</div> } } ReactDOM.render( <Clock />, document.getElementById('content') )
Recibirá un mensaje de error: Error de tipo no capturado: no se puede leer la propiedad 'currentTime' de nulo. Por lo general, los mensajes de error de JavaScript tienen los mismos beneficios que un vaso de agua fría para una persona que se está ahogando. Es bueno que al menos en este caso, JavaScript muestre un mensaje significativo.
El mensaje indica que el valor de currentTime no está definido. A diferencia de las propiedades, los estados no se establecen en el padre. Llamar a setState en render () también falla, porque creará un bucle (setState -> render -> setState ...) - y React informará un error.
Asignación de estado inicial
Ya has visto que antes de usar datos de estado en render (), debes inicializar el estado. Para establecer el estado inicial, use this.state en el constructor con la sintaxis de la clase ES6 React.Component. Recuerde llamar a super () con propiedades; de lo contrario, la lógica en el padre (React.Component) no funcionará:
class MyFancyComponent extends React.Component { constructor(props) { super(props) this.state = {...} } render() { ... } }
Al asignar el estado inicial, también puede agregar otra lógica, por ejemplo, establecer el valor de currentTime usando new Date (). Incluso puede usar toLocaleString () para obtener el formato de fecha / hora correcto para la ubicación actual del usuario, como se muestra a continuación (ch04 / reloj).
Listado 4.2. Constructor de componentes de reloj
class Clock extends React.Component { constructor(props) { super(props) this.state = {currentTime: (new Date()).toLocaleString()} } ... }
El valor de this.state debe ser un objeto. No entraremos en detalles de constructor () desde ES6; consulte el Apéndice D y el Resumen de ES6 en
github.com/azat-co/cheatsheets/tree/master/es6 . La conclusión es que, como en otros lenguajes OOP, se llama a un constructor (es decir, constructor ()) cuando se crea una instancia de la clase. El nombre del método constructor debería ser solo eso; Considere esta una de las reglas de ES6. Además, al crear el método constructor (), la llamada super () casi siempre debería incluirse en él, sin lo cual el constructor del padre no se ejecutaría. Por otro lado, si no define el método constructor (), la llamada a super () se asumirá por defecto.
El nombre currentTime es opcional; debe usar el mismo nombre más adelante cuando lea y actualice este estado.
El objeto de estado puede contener objetos anidados o matrices. El siguiente ejemplo agrega una serie de descripciones de libros al estado:
class Content extends React.Component { constructor(props) { super(props) this.state = { githubName: 'azat-co', books: [ 'pro express.js', 'practical node.js', 'rapid prototyping with js' ] } } render() { ... } }
El método constructor () se llama solo una vez, al crear un elemento React basado en la clase. Por lo tanto, puede establecer el estado directamente usando this.state solo una vez, en el método constructor (). No establezca ni actualice el estado directamente con this.state = ... en otro lugar, ya que esto puede tener consecuencias imprevistas.
Por lo tanto, solo obtiene el valor inicial, que rápidamente quedará obsoleto, en solo 1 segundo. ¿Quién necesita un reloj que no muestre la hora actual? Afortunadamente, hay un mecanismo para actualizar el estado actual.
Actualización de estado
El estado cambia mediante el método de la clase this.setState (datos, devolución de llamada). Cuando se llama a este método, React combina los datos con los estados actuales y llama a render (), después de lo cual llama a la devolución de llamada.
Definir una devolución de llamada en setState () es importante porque el método funciona de forma asíncrona. Si la aplicación depende del nuevo estado, puede usar esta devolución de llamada para asegurarse de que el nuevo estado esté disponible.
Si solo asume que el estado se ha actualizado sin esperar a que setState () se complete, es decir, que funcione sincrónicamente al realizar una operación asincrónica, puede producirse un error: el programa depende de actualizar los valores de estado, pero el estado sigue siendo antiguo.
Hasta ahora, hemos rendido el tiempo del estado. Ya sabes cómo configurar el estado inicial, pero debería actualizarse cada segundo, ¿verdad? Para hacer esto, use la función de temporizador del navegador setInterval () (http://mng.bz/P2d6), que actualizará el estado cada n milisegundos. El método setInterval () se implementa en casi todos los navegadores modernos como global, lo que significa que se puede usar sin bibliotecas o prefijos adicionales. Un ejemplo:
setInterval(()=>{ console.log('Updating time...') this.setState({ currentTime: (new Date()).toLocaleString() }) }, 1000)
Para iniciar la cuenta regresiva, debe llamar a setInterval () solo una vez. Creamos el método launchClock () únicamente para este propósito; Se llamará a launchClock () en el constructor. La versión final del componente se muestra en el Listado 4.3 (ch04 / clock / jsx / clock.jsx).
Se puede llamar al método setState () en cualquier lugar, no solo en el método launchClock () (que se llama en el constructor), como en el ejemplo. Normalmente, el método setState () se llama desde un controlador de eventos o como una devolución de llamada cuando se reciben o actualizan datos.
SUGERENCIA Un intento de cambiar el estado en el código con un comando de la forma this.state.name = 'nuevo nombre' no conducirá a nada. No conducirá a volver a renderizar y actualizar el modelo DOM real, lo que le gustaría. En la mayoría de los casos, un cambio de estado directo sin setState () es antipatrón y debe evitarse.
Es importante tener en cuenta que el método setState () solo actualiza los estados que se le pasaron (parcialmente o fusionados, pero sin un reemplazo completo). No reemplaza todo el objeto de estado cada vez. Por lo tanto, si solo uno de los tres estados ha cambiado, los otros dos permanecerán sin cambios. En el siguiente ejemplo, userEmail y userId no cambiarán:
constructor(props) { super(props) this.state = { userName: 'Azat Mardan', userEmail: 'hi@azat.co', userId: 3967 } } updateValues() { this.setState({userName: 'Azat'}) }
Si tiene la intención de actualizar los tres estados, tendrá que hacerlo explícitamente pasando los nuevos valores de estos estados a setState (). (También en el antiguo código, que ahora ya no funciona, el método this.replaceState () a veces se encuentra; está oficialmente en desuso 1. Como se puede adivinar por su nombre, reemplazó todo el objeto de estado con todos sus atributos).
Recuerde que llamar a setState () inicia la ejecución de render (). En la mayoría de los casos, funciona. En algunos casos especiales en los que el código depende de datos externos, puede iniciar una nueva representación llamando a this.forceUpdate (). Sin embargo, tales decisiones son indeseables, ya que depender de datos externos (en lugar del estado) hace que los componentes sean menos confiables y dependientes de factores externos (enlace estricto).
Como se mencionó anteriormente, se puede acceder al objeto de estado en la entrada this.state. En JSX, los valores de salida están encerrados entre llaves ({}), por lo tanto, para declarar una propiedad de estado en una vista (es decir, en el comando de retorno del método de representación), use la notación {this.state.NAME}.
La magia de reacción ocurre cuando usa datos de estado en una vista (por ejemplo, en la salida, en un comando if / else, como valor de atributo o valor de propiedad de un hijo), y luego pasa nuevos valores setState (). Bah! React actualiza todo el marcado HTML necesario para usted. Puede verificar esto en la consola de DevTools, donde se deben mostrar los ciclos "Actualizando ..." y "Representando ...". Y lo mejor es que esto solo afectará los elementos DOM mínimos mínimos obligatorios.
»Se puede encontrar más información sobre el libro en
el sitio web del editor»
Contenidos»
ExtractoCupón de 20% de descuento para vendedores ambulantes -
ReaccionarTras el pago de la versión en papel del libro, se envía una versión electrónica del libro por correo electrónico.