Hook de Otimização de Desempenho useMemo no React
O primeiro hook para otimização de
desempenho que vamos examinar
é o useMemo.
Este hook ajuda a armazenar em cache os resultados de operações que consomem muitos recursos entre os momentos de rerrenderização da tela e, consequentemente, pode ajudar a evitar cálculos volumosos desnecessários. Esse armazenamento em cache também é chamado de memoização.
Vamos ver como isso funciona. Vamos
criar um componente com um botão e
um título h3:
return (
<div>
<h3>Text</h3>
<button>click</button>
</div>
);
E agora vamos fazer com que ao clicar
no título, sua cor mude de laranja
para verde e vice-versa. Primeiro,
vamos criar um estado isGreen:
const [isGreen, setIsGreen] = useState(false);
Vamos adicionar no atributo style do título
uma condição para mudar a cor do título e
adicionar um manipulador de clique:
<h3 onClick={() => setIsGreen(!isGreen)}
style={{ color: isGreen ? 'green' : 'orangered' }}
>Text</h3>
Vamos supor que também tenhamos algum valor, que será incrementado em um a cada clique no nosso botão. Vamos criar um estado para ele:
const [num, setNum] = useState(0);
Vamos adicionar o tratamento do clique no botão:
<button onClick={() => setNum(num + 1)}>
cliques
</button>
Suponhamos também que tenhamos uma função
square, que retornará o
quadrado do valor num. O resultado
da chamada da função será armazenado em
uma variável result:
const result = square(num);
function square(num) {
return num * num;
}
Vamos exibir o result no texto do botão:
<button onClick={() => setNum(num + 1)}>
cliques: {result}
</button>
Como resultado, obtivemos o seguinte:
ao clicar no botão, o valor de
num muda, que é então elevado
ao quadrado, e ao clicar no título
a cor do título muda.
Temos um componente muito pequeno, tudo funciona rapidamente, apesar de que ao clicar no título para mudar sua cor, todo o componente é renderizado novamente, consequentemente, os cálculos vinculados ao botão também são refeitos, isso mesmo sem termos tocado nela. E agora imagine se nossos cálculos fossem complexos e tudo tivesse que ser recalculado a cada vez.
Vamos dificultar um pouco nossa função, agora ela vai "pensar" um pouco mais. Dessa forma, simularemos cálculos demorados:
function square(num) {
let startTime = performance.now();
while (performance.now() - startTime < 500) {
// Apenas não fazer nada ...
}
return num * num;
}
Agora clique no título. O que acontece é
que, devido ao longo tempo de execução da função
square (e nós não estamos tocando no botão!)
temos que esperar uma eternidade para
a cor do título mudar!
É aqui que o hook
useMemo vem nos salvar. Para isso, precisamos
passar como primeiro parâmetro uma função que calcula o
valor que queremos armazenar em cache.
Esta função deve ser pura e não
aceitar nenhum parâmetro. E como segundo
parâmetro - as dependências entre colchetes,
ou seja, todos os valores reativos
que participam no código da
função. Assim, em result
escreveremos agora a seguinte construção:
const result = useMemo(() => square(num), [num]);
Vamos clicar no título novamente. Agora,
se não tocarmos no botão com os cálculos
e, portanto, não alterarmos o valor do estado
num, nada é recalculado,
e o React exibe o valor em cache
no botão, então nosso título
muda de cor rapidamente.
Crie um componente App, coloque
nele um parágrafo. Crie um estado text
com o valor inicial 'react',
deixe o valor do estado ser exibido
como texto do parágrafo. Faça com que ao clicar
no parágrafo, um ponto de exclamação seja adicionado
ao final do texto.
Crie outro estado num, com
valor inicial 0. Coloque em
App outro parágrafo. Faça com que
ao clicar nele, o num
seja incrementado em 1.
E agora adicione em App a função
triple, que recebe
num como parâmetro e
retorna seu valor triplicado.
Coloque o resultado da chamada da função
na variável result. Exiba
result como texto do segundo
parágrafo. Clique sequencialmente nos parágrafos,
observe como os pontos de exclamação são
adicionados lentamente.
Corrija a situação, envolvendo a função lenta
triple em useMemo.