A memoização é uma técnica de otimização, semelhante ao armazenamento em cache. Ele funciona armazenando os resultados anteriores de uma chamada de função e usando esses resultados na próxima vez que a função for executada. É especialmente útil em aplicativos de computação pesada que repetem chamadas de função nos mesmos parâmetros.
Você pode usar memoization em JavaScript simples e também em React, de algumas maneiras diferentes.
Memorização em JavaScript
Para memorizar uma função em JavaScript, você precisa armazenar os resultados dessa função em um cache. O cache pode ser um objeto com os argumentos como chaves e os resultados como valores.
Quando você chama essa função, ela primeiro verifica se o resultado está presente no cache antes de ser executado. Se estiver, ele retornará os resultados armazenados em cache. Caso contrário, ele executa.
Considere esta função:
funçãoquadrado(número) {
Retorna num * num
}
A função recebe um argumento e retorna seu quadrado.
Para executar a função, chame-a com um número como este:
quadrado(5) // 25
Com 5 como argumento, square() será executado bem rápido. No entanto, se você calculasse o quadrado de 70.000, haveria um atraso notável. Não muito, mas um atraso, no entanto. Agora, se você chamasse a função várias vezes e passasse 70.000, haveria um atraso em cada chamada.
Você pode eliminar esse atraso usando a memorização.
const memoizedSquare = () => {
deixar esconderijo = {};
Retorna (num) => {
se (num em esconderijo) {
console.log('Reutilizando valor em cache');
Retorna esconderijo[número];
} senão {
console.log('Calculando o resultado');
deixar resultado = num * num;
// esconderijo a novoresultadovalorporpróximoTempo
esconderijo[número] = resultado;
Retorna resultado;
}
}
}
Neste exemplo, a função verifica se o resultado foi calculado antes, verificando se ele existe no objeto de cache. Se tiver retorna o valor já calculado.
Quando a função recebe um novo número, ela calcula um novo valor e armazena os resultados no cache antes de retornar.
Novamente, este exemplo é bem simples, mas explica como a memoização funcionaria para melhorar o desempenho de um programa.
Você deve memorizar apenas funções puras. Essas funções retornam o mesmo resultado quando você passa os mesmos argumentos. Se você usar memoização em funções impuras, não melhorará o desempenho, mas aumentará sua sobrecarga. Isso porque você escolhe a velocidade sobre a memória toda vez que memoriza uma função.
Memorização em React
Se você deseja otimizar os componentes do React, o React fornece memoização através do gancho useMemo(), React.memo e useCallBack().
Usando useMemo()
useMemo() é um Gancho de reação que aceita uma função e um array de dependências.
const memoizedValue = useMemo(() => computaExpensiveValue (a, b), [a, b]);
Ele memoriza o valor retornado dessa função. Os valores na matriz de dependência determinam quando a função é executada. Somente quando eles mudam é que a função é executada novamente.
Por exemplo, o componente App a seguir tem um valor memorizado chamado result.
importar { use o memorando } a partir de "reagir"
funçãoAplicativo(valor) {
const quadrado = (valor) => {
Retorna valor * valor
}
const resultado = useMemo(
() => quadrado (valor),
[ valor ]
);
Retorna (
<div>{resultado (5)}</div>
)
}
O componente App chama square() em cada renderização. O desempenho diminuirá se o componente App for renderizado muitas vezes devido a Reagir adereços alteração ou atualização de estado, especialmente se a função square() for cara.
No entanto, como useMemo() armazena em cache os valores retornados, a função quadrada não é executada em cada nova renderização, a menos que os argumentos na matriz de dependência sejam alterados.
Usando React.memo()
React.memo() é um componente de ordem superior que aceita um componente React e uma função como argumentos. A função determina quando o componente deve ser atualizado.
A função é opcional e se não for fornecida, o React.memo faz uma comparação superficial das props atuais do componente com suas props anteriores. Se os adereços forem diferentes, ele acionará uma atualização. Se os adereços forem os mesmos, ele ignora a nova renderização e reutiliza os valores memorizados.
A função opcional aceita as props anteriores e as props seguintes como argumentos. Você pode então comparar explicitamente essas props para decidir se deseja atualizar o componente ou não.
Reagir.memorando(Componente, [areEqual (prevProps, nextProps)])
Vejamos primeiro um exemplo sem o argumento de função opcional. Abaixo está um componente chamado Comentários que aceita as props name e email.
funçãoComentários ({nome, comentário, curtidas}) {
Retorna (
<div>
<p>{nome}</p>
<p>{Comente}</p>
<p>{curtidas}</p>
</div>
)
}
O componente de comentários memoizados terá o React.memo enrolado assim:
const MemoizedComment = React.memo (Comentário)
Você pode chamá-lo e chamá-lo como qualquer outro componente React.
<MemoizedComment name="Mary" comentar="A memorização é ótima" curtidas=1/>
Se você quiser realizar a comparação de props por conta própria, passe a seguinte função para React.memo como o segundo argumento.
importar Reagir a partir de "reagir"
funçãocheckCommentProps(prevProps, nextProps) {
Retorna prevProps.name nextProps.name
&& prevProps.comment nextProps.comment
&& prevProps.likes nextProps.likes
}
const MemoizedComment = React.memo (Comentários, checkCommentProps)
Se checkProfileProps retornar true, o componente não será atualizado. Caso contrário, ele é renderizado novamente.
A função customizada é útil quando você deseja customizar a nova renderização. Por exemplo, você pode usá-lo para atualizar o componente Comentários somente quando o número de curtidas for alterado.
Ao contrário do gancho useMemo() que memoriza apenas o valor retornado de uma função, o React.memo memoriza a função inteira.
Use React.memo apenas para componentes puros. Além disso, para reduzir os custos de comparação, memorize apenas os componentes cujos suportes mudam com frequência.
Usando useCallBack()
Você pode usar o gancho useCallBack() para memorizar componentes de função.
const memoizedCallback = useCallback(
() => {
fazer Algo (a, b);
},
[a, b],
);
A função é atualizada apenas quando os valores na matriz de dependência são alterados. O gancho funciona como o callback useMemo(), mas memoriza o componente da função entre renderizações em vez de memorizar valores.
Considere o exemplo a seguir de uma função memorizada que chama uma API.
importar { useCallback, useEffect } a partir de "reagir";
const Componente = () => {
const getData = useCallback(() => {
console.log('chamar uma API');
}, []);
useEfeito(() => {
Obter dados();
}, [Obter dados]);
};
A função getData() chamada em useEffect será chamada novamente somente quando o valor de getData for alterado.
Você deve memorizar?
Neste tutorial, você aprendeu o que é memoization, seus benefícios e como implementá-lo em JavaScript e React. No entanto, você deve saber que o React já é rápido. Na maioria dos casos, memorizar componentes ou valores adiciona custos de comparação e não melhora o desempenho. Por isso, memoize apenas componentes caros.
O React 18 também introduziu novos ganchos como useId, useTransition e useInsertionEffect. Você pode usá-los para melhorar o desempenho e a experiência do usuário dos aplicativos React.