Tecnologia

Para conferir a parte #1 deste artigo, clique aqui!

Olá turma! Neste segundo episódio do React 18, vou tratar de um assunto muito importante que vai ajudar a entender uma das coisas que o React faz para trabalhar, e que afeta diretamente a performance e sequência de execução.

Estou me referindo ao Automatic batching.

Mas que raios é Automatic batching?

Batching (lotes), é quando o React prepara várias atualizações de estado, formando um grupo que será executado em uma única renderização, o que por sua vez gera um ganho de desempenho na performance de sua aplicação.

Quando você alterar uma variável através do setState dentro de uma função ou callback, O React não executa uma por uma. Ao invés disso, ele prepara o que conhecemos por Batching (lote) e executa todos setStates juntos.

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

   const handleEatCookies = useCallback(() => {
       setAmountCookies(oldState => ++oldState);// Não sofre renderização, mas é adicionado ao lote.
       setIsOdd(oldState => !oldState);// Não sofre renderização, mas é adicionado ao lote.
       //React renderiza os estados do lote uma única vez!
   }, [setIsOdd, setAmountCookies]};

   return (
<div>
<h1 style={{ color: isOdd? "blue" : "red" }}>{count} Cookies comidos!</h1>
<button onClick={handleEatCookies }>Comer um Cookie</button>
</div>
   );
}

E qual é a novidade nisso tudo?

Para entendermos o que vem de novo, precisamos esclarecer o que há de velho. Entendemos que o batching é ótimo para o desempenho, porque evita renderizações desnecessárias.

No entanto, isso acontecia apenas em manipuladores de eventos DOM. Portanto, Promises, timeouts ou outros manipuladores não tiravam vantagem disso.

const handleEatCookies = useCallback(() => {
Promise.resolve().then(() => {
setAmountCookies(oldState => ++oldState);// Sofre renderização.
setIsOdd(oldState => !oldState);// Sofre renderização.
});
}, [setIsOdd, setAmountCookies]};
const handleEatCookies = useCallback(() => {
setTimeout(() => {
setAmountCookies(oldState => ++oldState);// Sofre renderização.
setIsOdd(oldState => !oldState);// Sofre renderização.
}, 10000);
}, [setIsOdd, setAmountCookies]};

React 18 enviará atualizações de estado em lote, independentemente de onde acontecerem.

Ou seja: Promises, timeouts e outros terão o benefício do batching, desde que seja seguro fazê-lo. Isso resulta em um melhor desempenho, sem qualquer envolvimento adicional.

Preciso que minha função renderize mais de uma vez, o que eu faço?

Atualmente, se quisermos que nossos states renderizem antes de finalizar uma função, podemos fazer um sheat parecido com isso:

const handleEatCookies = useCallback(() => {
function resolveAmount(){
setAmountCookies(oldState => ++oldState);// Sofre renderização.
};
resolveAmount();
setIsOdd(oldState => !oldState);// Não sofre renderização, mas é adicionado ao lote.
//React renderiza os estados do lote uma única vez!
}, [setIsOdd, setAmountCookies]};

E com o React 18, ganhamos uma função do ReactDOM, chamada flushSync, que serve para criar o batching que renderiza após sua declaração.

import { flushSync **}** from "react-dom";
//...
const handleEatCookies = useCallback(() => {
flushSync(() => {
setAmountCookies(oldState => ++oldState);// Não sofre renderização, mas é adicionado ao lote
});
//React renderiza os estados do lote acima!
flushSync(() => {
setIsOdd(oldState => !oldState);// Não sofre renderização, mas é adicionado ao lote.
});
//React renderiza os estados do lote acima!
}, [setIsOdd, setAmountCookies]};
//...

A expansão do automatic batching para os demais níveis e tipos de funções irão facilitar para que possamos criar aplicações mais performáticas, e o flushSync trará uma forma elegante para que possamos fugir do padrão quando necessário.

Se ficou alguma dúvida ou quer saber mais sobre algo que mencionei nesse artigo, ou apenas para dizer o que achou, não deixe de escrever nos comentários, isso vai ser muito importante para que eu possa trazer conteúdos relevantes.

Muito obrigado por ter lido até aqui e até o próximo capítulo.

Esse artigo foi desenvolvido por Tadeu Agostini, desenvolvedor front-end Web da Zappts.