Kiedy stan komponentu się zmienia, React przerysowuje go na nowo. Dzieje się to także z innymi komponentami, które komponent-rodzic zawiera.
Może się zdarzyć, że takie przerysowywanie komponentu za każdym razem nie jest dobrym pomysłem. Wydajność aplikacji może spaść. I w takich przypadkach można skorzystać z memo. Po jego użyciu React zapamiętuje komponent i pomija (jeśli nie jest to potrzebne) ponowne przerysowanie komponentu.
Z memo należy korzystać rozważnie — tylko wtedy, gdy ma to sens.
Żeby komponent został "zapamiętany" przekazujemy go do funkcji memo. Od tego momentu, gdy użyjemy tak przygotowany komponent (MemoizedUser), React będzie używać jego zapamiętaną wersję, dopóty dopóki jego właściwości: name lub age będą mieć te same wartości. Jeśli wartość dla przynajmniej jednego parametru komponentu zostanie zmieniona, to zostanie on przerysowany i zapamiętany dla nowych wartości.
Składnia memo
Funkcja memo zawiera więcej niż jeden parametr:
memo(Component, arePropsEqual?)
Component — Tutaj przekazujemy komponent, który chcemy, żeby został zapamiętany.
arePropsEqual — Jest to parametr opcjonalny. To funkcja, która informuje React, czy komponent powinien zostać przerysowany. Przyjmuje dwa parametry: pierwszy to wartości z poprzedniego stanu komponentu. Drugi aktualne wartości stanu. Ta funkcja powinna zwrócić true jeśli oba stany mają te samo wartości — nic się nie zmieniło, więc komponent nie musi być przerysowany.
Komponent jest "czysty" - Dla tych samych wartości zawsze wyświetla ten sam wynik.
Komponent jest często przerysowywany.
Komponent staje się coraz większy. Przez co jego częste przerysowywanie staje się kosztowne.
Komponent jest często przerysowywany z tymi samymi wartościami.
Kiedy nie używać memo?
Komponent zwykle jest wyświetlany z różnymi wartościami.
Komponent nie jest duży i nie robi czasochłonnych obliczeń.
Uwaga na funkcje zwrotne!
Kiedy przekazujesz do komponentu funkcję zwrotną (ang. callback) i zamierzasz skorzystać z memo, uważaj, jak to robisz. Możesz popsuć zapamiętywanie komponentu!
W powyższym przykładzie zapamiętywanie komponentu przez memo jest popsute. Dodaj console.log w komponencie User i klikaj w przycisk "Janusz". Komponent MemoizedUser cały czas jest przerysowywany na nowo? Co się dzieje?!
Problem jest w tej linijce:
onSendMessage={() =>console.log(`Send message to: ${user.name}`)
Za każdym razem, gdy stan komponentu App się zmienia do onSendMessage przekazywana jest nowa instancja funkcji zwrotnej. A skoro nowa wartość to komponent MemoizedUser zostanie przerysowany na nowo! I tak za każdym razem...