Executando verificação de segurança...
6

React.memo: evitando re-renderizações

Hoje esbarrei com um problema em React que ainda não havia encontrado, e o React.memo() foi a solução.

O problema:

Estou desenvolvendo um site que faz certo tratamento de imagens usando várias layers de <canvas>. Porém quando há alterações, para evitar um flick durante o processamento da imagem, o site deve exibir a versão anterior até que a proxima esteja pronta. Então eu fazia algo assim:

return (
  <div className={classes.container}>
    <div className={currentCanvasIsRendering ? 'hide' : 'show'}> 
      {currentLayer}
    </div>
    <div className={currentCanvasIsRendering ? 'show' : 'hide'}> 
      {previousLayer}
    </div>
  </div>
)

Sendo que quando havia uma mudança, eu fazia a seguinte operação:

const nextLayer = (<MyCanvasComponent data={data} onRender={() => setCurrentCanvasIsRendering(false)}>);

setCurrentCanvasIsRendering(true);
setPreviousLayer(currentLayer);
setCurrentLayes(nextLayer);

Ou seja, eu pegava o layer atual e continuava exibindo enquanto o proximo renderizava.

Até aí tudo bem, o problema é que o react não entendia isso. Ele re-renderizava inclusive o layer anterior, e como meu processo de renderizar é relativamente lento, isso impedia a minha logica de funcionar (mostra o antigo enquanto o novo carrega)

A solução

O problema é que o react não entende por padrão que um componente é o mesmo, por mais que suas propriedades não mudem, e acaba renderizando novamente.

Para evitar isso, bastou ir no componente MyCanvasComponent e mudar o export para:

import { memo } from 'react';

...

export default memo(MyCanvasComponent);

E isso faz o react entender que não precisa renderizar aquele componente novamente.

Fonte: https://react.dev/reference/react/memo

Carregando publicação patrocinada...
1

Realmente o Memo é muito interessante para evitar re-renderizações desnecessárias, porém também temos que levar em consideração que se, o componente for muito simples o custo de se "memorizar" é maior do que re-renderizar o mesmo. Então, entendo que deve ser feito uma análise para ver se realmente é necessário! Parabéns pelo post.

1

De fato, assim como o useMemo dentro de um componente só deve ser usado para tarefas mais complexas.

No meu caso realmente é porque cada Canvas leva entre 5 a 30ms para renderizar dependendo do dispositivo, e na verdade são 7 layera sobrepostos, em que só posso exibir depois que tudo renderiza.

1

Se essa solução foi feita apenas para otimização, show de bola, porque na documentação desse hook tem uma observação:

Você deve confiar apenas no memo como uma otimização de desempenho. Se o seu código não funcionar sem ele, encontre o problema subjacente e corrija-o primeiro. Então você pode adicionar memo para melhorar o desempenho.

Enfim, boa sorte com teu projeto ai manin 😎🤙

1

Eu vi isso na documentação, e fiquei confuso. Funcionar, meu codigo funciona sem o memo. Porém não da forma que eu queria, pois o componente é recriado e portanto todo o processamento do canvas é feito novamente.