Blog
Cambios en la actualización de React 18 – Parte #2

Cambios en la actualización de React 18 – Parte #2

React 18 y el Automatic batching.

14 de outubro de 2021

Para consultar la parte #1 de este artículo, ¡haz clic aquí!

React 18

¡Hola a todos! En este segundo episodio de React 18, voy a tratar un tema muy importante que ayudará a entender una de las cosas que React hace para funcionar, y que afecta directamente el rendimiento y la secuencia de ejecución.

Me refiero al Automatic batching.

¿Pero qué demonios es Automatic batching?

Batching (lotes), es cuando React prepara varias actualizaciones de estado, formando un grupo que se ejecutará en una única renderización, lo que a su vez genera una ganancia de rendimiento en el desempeño de su aplicación.

Cuando cambias una variable a través de setState dentro de una función o callback, React no las ejecuta una por una. En su lugar, prepara lo que conocemos como Batching (lote) y ejecuta todos los setStates juntos.

const App = () => {
  const [amountCookies, setAmountCookies] = useState(0);
  const [isOdd, setIsOdd] = useState(false);

  const handleEatCookies = useCallback(() => {
    setAmountCookies(oldState => ++oldState);// No sufre renderización, pero se agrega al lote.
    setIsOdd(oldState => !oldState);// No sufre renderización, pero se agrega al lote.
    //React renderiza los estados del lote una sola vez!
  }, [setIsOdd, setAmountCookies]};

  return (<br/><div><br/><h1 style={{ color: isOdd? “blue” : “red” }}>{count} ¡Galletas comidas!</h1><br/><button onClick={handleEatCookies }>Comer una Galleta</button><br/></div><br/>   );
}

¿Y qué hay de nuevo en todo esto?

Para entender lo que es nuevo, necesitamos aclarar lo que es viejo. Entendemos que el batching es genial para el rendimiento, porque evita renderizaciones innecesarias.

Sin embargo, esto solo ocurría en manejadores de eventos DOM. Por lo tanto, Promises, timeouts u otros manejadores no sacaban provecho de esto.

const handleEatCookies = useCallback(() => {
Promise.resolve().then(() => {
setAmountCookies(oldState => ++oldState);// Sufre renderización.
setIsOdd(oldState => !oldState);// Sufre renderización.
});
}, [setIsOdd, setAmountCookies]};
const handleEatCookies = useCallback(() => {
setTimeout(() => {
setAmountCookies(oldState => ++oldState);// Sufre renderización.
setIsOdd(oldState => !oldState);// Sufre renderización.
}, 10000);
}, [setIsOdd, setAmountCookies]};

React 18 enviará actualizaciones de estado en lotes, independientemente de dónde ocurran.

Es decir: Promises, timeouts y otros tendrán el beneficio del batching, siempre que sea seguro hacerlo. Esto resulta en un mejor rendimiento, sin ninguna participación adicional.

Necesito que mi función renderice más de una vez, ¿qué hago?

Actualmente, si queremos que nuestros states rendericen antes de finalizar una función, podemos hacer un truco parecido a esto:

const handleEatCookies = useCallback(() => {
function resolveAmount(){
setAmountCookies(oldState => ++oldState);// Sufre renderización.
};
resolveAmount();
setIsOdd(oldState => !oldState);// No sufre renderización, pero se agrega al lote.
//React renderiza los estados del lote una sola vez!
}, [setIsOdd, setAmountCookies]};

Y con React 18, obtenemos una función de ReactDOM, llamada flushSync, que sirve para crear el batching que renderiza después de su declaración.

import { flushSync } from “react-dom”;
//…
const handleEatCookies = useCallback(() => {
flushSync(() => {
setAmountCookies(oldState => ++oldState);// No sufre renderización, pero se agrega al lote
});
//¡React renderiza los estados del lote arriba!
flushSync(() => {
setIsOdd(oldState => !oldState);// No sufre renderización, pero se agrega al lote.
});
//¡React renderiza los estados del lote arriba!
}, [setIsOdd, setAmountCookies]};
//…

La expansión del automatic batching para los demás niveles y tipos de funciones facilitará que podamos crear aplicaciones más performáticas, y flushSync traerá una forma elegante para que podamos escapar del patrón cuando sea necesario.

Si te quedó alguna duda o quieres saber más sobre algo que mencioné en este artículo, o solo para decir lo que te pareció, no dudes en escribir en los comentarios, será muy importante para mí poder traer contenido relevante.

Muchas gracias por haber leído hasta aquí y hasta el próximo capítulo.

Tadeu Agostini

Este artículo fue desarrollado por Tadeu Agostini, desarrollador front-end Web de Zappts.