No desenvolvimento de software, geralmente somos obcecados com ganhos de desempenho e como fazer nossos aplicativos funcionarem mais rápido para oferecer aos usuários uma experiência melhor.

Memoização é uma das maneiras de otimizar o desempenho. Neste artigo, vamos explorar como funciona no React.

O que é memoização?

Em termos simples, a memoização é um processo que nos permite armazenar em cache os valores de chamadas de funções recursivas/caras para que na próxima vez que a função for chamada com o (s) mesmo (s) argumento (s), o valor em cache seja retornado em vez de recalcule a função.

Isso garante que nossos aplicativos sejam executados com mais rapidez, pois evitamos o tempo que normalmente levaria para reexecutar a função, retornando um valor que já está armazenado na memória.

Por que usar memoização no React?

Nos componentes funcionais do React, quando os adereços em um componente são alterados, todo o componente é renderizado novamente por padrão. Em outras palavras, se algum valor em um componente for atualizado, todo o componente será renderizado novamente, incluindo funções/componentes que não tiveram seus valores/props alterados.

Vejamos um exemplo simples de onde isso acontece. Criaremos um aplicativo básico que informa aos usuários qual vinho combina melhor com o queijo que eles selecionaram.

Começaremos configurando dois componentes. O primeiro componente permitirá ao usuário selecionar um queijo. Em seguida, exibirá o nome do vinho que combina melhor com aquele queijo. O segundo componente será filho do primeiro componente. Neste componente, nada muda. Usaremos esse componente para controlar quantas vezes o React é renderizado novamente.

Vamos começar com nosso componente pai: .

NB , os classNames usados ​​neste exemplo vêm de Tailwind CSS .

//components/parent-component.js
importar contagens de"./counts";
botão de importação de"./button";
import {useState, useEffect} de"react";
importar constantes de"../utils";
const {MOZARELLA, CHEDDAR, PARMESAN, CABERNET, CHARDONAY, MERLOT}=constantes; função padrão de exportação ParentComponent () { const [cheeseType, setCheeseType]=useState (""); const [vinho, setWine]=useState (""); const whichWineGoesBest=()=> { switch (cheeseType) { case MOZARELLA: retornar setWine (CABERNET); case CHEDDAR: retornar setWine (CHARDONAY); case PARMESAN: retornar setWine (MERLOT); predefinição: CHARDONAY; } }; useEffect (()=> { deixe montado=verdadeiro; if (montado) { whichWineGoesBest (); } return ()=> (montado=falso); }, [cheeseType]); Retorna ( 

Sem React.memo () ou useMemo ()

Selecione um queijo e diremos qual vinho fica melhor!

setCheeseType (MOZARELLA)}/> setCheeseType (CHEDDAR)}/> setCheeseType (PARMESAN)}/>
{cheeseType && (

Para {cheeseType}, {wine} {""} vai melhor.

)}
); }

O segundo componente é um componente que rastreia quantas vezes todo o componente é renderizado novamente.

//components/counts.js
import {useRef} de"react";
função padrão de exportação Counts () { const renderCount=useRef (0); Retorna ( 

Nada mudou aqui, mas agora renderizei: {""} {(renderCount.current ++)} vez (es)

); }

Aqui está o exemplo acima em ação quando clicamos no nome de um queijo:

Exemplo de React Without Memoization

Nosso componente em nosso conta quantas vezes as alterações no força o componente para renderizar novamente.

Atualmente, clicar no nome de um queijo irá atualizar o nome do queijo a ser exibido. Ele também atualizará o nome do vinho a ser exibido. Não apenas o será renderizado novamente, mas o componente também será renderizado novamente, mesmo que nada dentro dele tenha mudado.

Imagine ter um componente exibindo milhares de dados, e cada vez que o usuário clica em um botão, todos os dados nesse componente ou árvore são renderizados novamente quando não precisam. É aqui que React.memo () ou useMemo () se torna necessário para nos fornecer otimizações de desempenho.

Agora, vamos explorar React.memo e, em seguida, useMemo () . Depois disso, compararemos as diferenças entre eles e aprenderemos quando você deve usar um em vez do outro.

O que é React.memo () ?

React.memo () foi lançado com React v16.6 . Embora os componentes da classe já permitam que você controle os re-renderizadores com o uso de PureComponent ou shouldComponentUpdate , React 16.6 introduziu a capacidade de fazer o mesmo com componentes funcionais.

React.memo () é um componente de ordem superior (HOC) , que é um nome extravagante para um componente que pega um componente como um suporte e retorna um componente que evita que um componente seja renderizado novamente se os acessórios (ou valores dentro dele) tiverem não mudou.

Usaremos o mesmo exemplo acima, mas usaremos React.memo () em nosso componente . Tudo o que precisamos fazer é envolver nosso componente com React.memo () como abaixo:

 import {useRef} de"react";
function Counts () { const renderCount=useRef (0); Retorna ( 

Nada mudou aqui, mas agora renderizei: {""} {(renderCount.current ++)} vez (es)

); } exportar React.memo (contagens) padrão;

Agora, quando selecionamos um tipo de queijo clicando nele, nosso componente não será renderizado novamente.

Exemplo usando React.memo ()

O que é useMemo () ?

Embora React.memo () seja um HOC, useMemo () é um React Hook. Com useMemo () , podemos retornar valores memoizados e evitar uma nova renderização se as dependências de uma função não tiverem mudado.

Para usar useMemo () em nosso código, os desenvolvedores do React têm alguns conselhos para nós :

  • Você pode confiar em useMemo () como uma otimização de desempenho, não como uma garantia semântica
  • Cada valor referenciado dentro da função também deve aparecer na matriz de dependências

Para nosso próximo exemplo, faremos algumas alterações em nosso . O código abaixo mostra apenas as novas mudanças no que criamos anteriormente.

//components/parent-component.js
.
.
import {useState, useEffect, useRef, useMemo} de"react";
importar UseMemoCounts de"./use-memo-counts"; função padrão de exportação ParentComponent () { . . const [times, setTimes]=useState (0); const useMemoRef=useRef (0); const incrementUseMemoRef=()=> useMemoRef.current ++; //retire o comentário da próxima linha para testar se  irá renderizar novamente a cada vez que o pai renderizar novamente. //const memoizedValue=useMemoRef.current ++; //a próxima linha garante que  apenas renderize quando o valor dos tempos mudar
const memoizedValue=useMemo (()=> incrementUseMemoRef (), [vezes]); . . Retorna ( 
. .
setTimes (times + 1)} > Forçar renderização
); }

Primeiro, estamos trazendo o importante gancho useMemo () . Também estamos trazendo o gancho useRef () para nos ajudar a rastrear quantas re-renderizações ocorreram em nosso componente. Em seguida, declaramos um estado times que mais tarde atualizaremos para acionar/forçar uma nova renderização.

Posteriormente, declaramos uma variável memoizedValue que armazena o valor retornado pelo gancho useMemo () . O gancho useMemo () chama nossa função incrementUseMemoRef , que incrementa o valor de nosso useMemoRef.current em um cada vez que houver uma mudança no dependências, ou seja, o valor times muda.

Criamos então um botão que atualiza o valor de vezes quando clicado. Clicar neste botão fará com que nosso gancho useMemo () seja acionado, o valor de memoizedValue seja atualizado e nosso componente renderizar novamente.

Para este exemplo, também renomeamos nosso componente para e agora leva um memoizedValue prop.

Esta é a aparência:

//components/use-memo-counts.js function UseMemoCounts ({memoizedValue}) { Retorna ( 

Só vou renderizar novamente quando você clicar em Forçar renderização.

Eu agora renderizei: {memoizedValue} vez (es)

); } exportar UseMemoCounts padrão;

Agora, quando clicamos em qualquer um dos botões de queijo , nosso memoizedValue não é atualizado. Mas quando clicamos no botão Forçar renderização , vemos que nosso memoizedValue é atualizado e o componente é renderizado novamente.

Usememo () example

Se você comentar nossa linha memoizedValue atual e descomentar a linha acima dela:

 const memoizedValue=useMemoRef.current ++;

… você verá que o componente será renderizado novamente cada vez que o for renderizado.

Resumindo: as principais diferenças entre React.memo () e useMemo()

No exemplo acima, podemos ver as principais diferenças entre React.memo () e useMemo () :

  • React.memo () é um componente de ordem superior que podemos usar para envolver componentes que não queremos renderizar novamente, a menos que os adereços dentro deles mudem
  • useMemo () é um React Hook que podemos usar para agrupar funções em um componente. Podemos usar isso para garantir que os valores dentro dessa função sejam recalculados apenas quando uma de suas dependências mudar

Embora a memoização possa parecer um truque bacana para usar em qualquer lugar, você deve usá-la apenas quando realmente precisar desses ganhos de desempenho. A memorização usa espaço de memória na máquina em que está sendo executada e, como tal, pode levar a efeitos indesejados.

E isso conclui este artigo!

Você pode acessar o código completo deste exemplo no GitHub e um exemplo ao vivo aqui .

A postagem React.memo () vs. useMemo () : Principais diferenças e casos de uso apareceram primeiro no LogRocket Blog .

Source link