Aqui está um gancho que conta o número de renderizações
import { useRef } from 'react';
export const useRenderCount = () => {
const renderCount = useRef(0);
return ++renderCount.current;
};
Brincando, tenho o seguinte teste (também tentei variantes sem o await act).
it('updates when state changes', async () => {
const { result } = renderHook(() => {
const [text, setText] = useState('');
const renderCount = useRenderCount();
return { setText, renderCount, text };
});
expect(result.current.renderCount).toBe(1);
await act(async () => result.current.setText('a'));
expect(result.current.renderCount).toBe(2);
await act(async () => result.current.setText('a'));
expect(result.current.renderCount).toBe(2);
await act(async () => result.current.setText('b'));
expect(result.current.renderCount).toBe(4); // why also 4? I am expecting 3
});
Então presumi o seguinte, pode ser que esteja enfileirando as renderizações, mas quando fiz isso
it('updates when state changes', async () => {
const { result } = renderHook(() => {
const [text, setText] = useState('');
const renderCount = useRenderCount();
return { setText, renderCount, text };
});
expect(result.current.renderCount).toBe(1);
await act(async () => result.current.setText('a'));
expect(result.current.renderCount).toBe(2);
await act(async () => result.current.setText('a'));
expect(result.current.renderCount).toBe(2);
await act(async () => result.current.setText('a'));
expect(result.current.renderCount).toBe(2);
await act(async () => result.current.setText('a'));
expect(result.current.renderCount).toBe(2);
await act(async () => result.current.setText('b'));
expect(result.current.renderCount).toBe(4); // why still 4? if it was queueing it should be 6
});
a. O React renderizará a primeira alteração.
b. O React renderizará para repetir o mesmo valor.
c. No entanto, o React não renderizará mais nenhuma repetição do mesmo valor.
Exemplo,
O código de exemplo mostra o mesmo.
Aplicativo.js
Execução de teste
Exibição do navegador - depois de clicar em todos os quatro botões, o componente foi renderizado por apenas 3 vezes, incluindo a renderização inicial. Duas renderizações foram ignoradas
Voltando à sua pergunta:
Pergunta 1
Você está recebendo 4 aqui, como discutimos acima, o React renderizará para a primeira repetição da mudança. Portanto, a atualização de dois estados com o texto 'a' será contada aqui.
Pergunta 2
Ele dá 4, pois ignora a 3ª e 4ª repetição do texto 'a'.
Para mais sobre isso, veja uma pergunta semelhante e sua discussão aqui. Por que ele re-renderiza mesmo quando o estado é o mesmo?
Para uma documentação abrangente sobre este tópico, consulte o documento aqui, Respostas do blog: um guia (quase) completo sobre o comportamento de renderização do React