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.