Estoy tratando de averiguar cuándo se produce la nueva representación al actualizar el estado en React con useState hook. En el siguiente código, al hacer clic en el botón se activa la función handleClick que contiene un setTimeout. La devolución de llamada dentro de setTimeout se ejecuta después de 1 segundo, lo que actualiza el conteo de la variable de estado llamando a setCount. Luego, un registro de la consola imprime un mensaje.
El orden en el que espero que aparezcan los registros de la consola una vez que se hace clic en el botón es:
Sin embargo, el orden que veo después de ejecutar este código es:
¿Cómo es que aparece "'Count in render', 1" antes de "'Count post update in setTimeout', 0"? ¿SetCount no da como resultado la programación de una nueva representación que no es inmediata? ¿No debería la consola iniciar sesión inmediatamente después de que la llamada a la función setCount siempre se ejecute antes de que se active la nueva representación?
function AppFunctional() { const [count, setCount] = React.useState(0); const handleClick = () => { console.log('Count before update', count); setTimeout(() => { setCount(count + 1); console.log('Count post update in setTimeout', count); }, 1000); }; console.log('Count in render', count); return ( <div className="container"> <h1>Hello Functional Component!</h1> <p>Press button to see the magic :)</p> <button onClick={handleClick}>Increment</button> {!!count && ( <div className="message">You pressed button {count} times</div> )} </div> ); } ReactDOM.render(<AppFunctional />, document.querySelector('.react')); <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div class='react'></div>¿setCount no da como resultado la programación de una nueva representación que no es inmediata? ¿No debería la consola iniciar sesión inmediatamente después de que la llamada a la función setCount siempre se ejecute antes de que se active la nueva representación?
Bajo el capó, React optimiza las re-renderizaciones al ponerlas en cola y agruparlas en lotes cuando puede determinar que es seguro hacerlo . Cuando está en una función que React entiende (como un componente funcional o una devolución de llamada de gancho), si llama a un setter de estado en una de esas funciones, React sabrá que es seguro retrasar la actualización de estado hasta que finalice su procesamiento, por ejemplo , hasta que se hayan ejecutado todas las devoluciones de llamada de efectos/notas/etc., y hasta que todos los componentes del estado original se hayan pintado en la pantalla.
Pero cuando llama a una actualización de estado fuera de una función React incorporada, React no sabe lo suficiente sobre su comportamiento para saber cuándo podrá volver a renderizarse a continuación si retrasa la actualización de estado. La llamada setTimeout no se llama desde dentro del ciclo de vida de React, por lo que es mucho más difícil agrupar actualizaciones y optimizarlas, por lo que, en lugar de que React intente adivinar cómo podría hacerse de forma segura y asincrónica, se vuelve a procesar de inmediato.