Para componentes de clase, this.setState llama por lotes si está dentro de los controladores de eventos. Pero, ¿qué sucede si el estado se actualiza fuera del controlador de eventos y usa useState ?
function Component() { const [a, setA] = useState('a'); const [b, setB] = useState('b'); function handleClick() { Promise.resolve().then(() => { setA('aa'); setB('bb'); }); } return <button onClick={handleClick}>{a}-{b}</button> } ¿Producirá aa - bb de inmediato? ¿O será aa - b y luego aa - bb ?
TL; DR : si los cambios de estado se activan de forma asíncrona (por ejemplo, envueltos en una promesa), no se procesarán por lotes; si se activan directamente, se procesarán por lotes.
Configuré un sandbox para probar esto: https://codesandbox.io/s/402pn5l989
import React, { Fragment, useState } from 'react'; import ReactDOM from 'react-dom'; import './styles.css'; function Component() { const [a, setA] = useState('a'); const [b, setB] = useState('b'); console.log('a', a); console.log('b', b); function handleClickWithPromise() { Promise.resolve().then(() => { setA('aa'); setB('bb'); }); } function handleClickWithoutPromise() { setA('aa'); setB('bb'); } return ( <Fragment> <button onClick={handleClickWithPromise}> {a}-{b} with promise </button> <button onClick={handleClickWithoutPromise}> {a}-{b} without promise </button> </Fragment> ); } function App() { return <Component />; } const rootElement = document.getElementById('root'); ReactDOM.render(<App />, rootElement);Hice dos botones, uno activa los cambios de estado envueltos en una promesa como en su ejemplo de código, el otro activa los cambios de estado directamente.
Si observa la consola, cuando presiona el botón "con promesa", primero mostrará a aa y bb , luego a aa y b bb .
Entonces, la respuesta es no, en este caso, no se procesará aa - bb de inmediato, cada cambio de estado desencadena un nuevo procesamiento, no hay procesamiento por lotes.
Sin embargo, cuando hace clic en el botón "sin promesa", la consola mostrará a aa y b bb de inmediato.
Entonces, en este caso, React procesa por lotes los cambios de estado y hace un procesamiento para ambos juntos.
Actualmente en React v16 y versiones anteriores, solo las actualizaciones dentro de los controladores de eventos de React, como click o onChange , etc., se procesan por lotes de manera predeterminada. Entonces, al igual que las actualizaciones de estado de las clases, se procesan por lotes de manera similar en los ganchos
Hay una API inestable para forzar el procesamiento por lotes fuera de los controladores de eventos en casos excepcionales cuando lo necesite.
ReactDOM.unstable_batchedUpdates(() => { ... })Existe un plan para procesar por lotes todas las actualizaciones de estado en una versión futura en React probablemente v17 o superior.
Ahora también, si las llamadas de actualización de estado desde el controlador de eventos están en funciones asíncronas o se activan debido a un código asíncrono, no se procesarán por lotes donde se procesarán las actualizaciones directas.
Donde sin el código de sincronización, las actualizaciones de estado se procesan por lotes y las actualizaciones de código asíncrono no
function App() { const [count1, setCount1] = useState(0); const [count2, setCount2] = useState(0); // async update from useEffect useEffect(() => { setTimeout(() => { setCount1(count => count + 1); setCount2(count => count + 2); }, 3000); }, []); const handleAsyncUpdate = async () => { await Promise.resolve("state updated"); setCount1(count => count + 2); setCount2(count => count + 1); }; const handleSyncUpdate = () => { setCount1(count => count + 2); setCount2(count => count + 1); }; console.log("render", count1, count2); return ( <div className="App"> <h1>Hello CodeSandbox</h1> <h2>Start editing to see some magic happen!</h2> <button type="button" onClick={handleAsyncUpdate}> Click for async update </button> <button type="button" onClick={handleSyncUpdate}> Click for sync update </button> </div> ); }Si el controlador react-based , procesa las actualizaciones por lotes. Esto es cierto para las llamadas setState o useState.
Pero no se procesa por lotes automáticamente en caso de que el evento non-react , es decir, setTimeout, llamadas Promise. En definitiva cualquier evento desde Web APIs .