{"id":26953,"date":"2024-03-04T05:00:00","date_gmt":"2024-03-04T04:00:00","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=26953"},"modified":"2024-07-22T14:14:32","modified_gmt":"2024-07-22T12:14:32","slug":"wydajnosc-w-aplikacjach-react-jak-sprostac-wyzwaniom","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/wydajnosc-w-aplikacjach-react-jak-sprostac-wyzwaniom\/","title":{"rendered":"Wydajno\u015b\u0107 w aplikacjach React \u2013 jak sprosta\u0107 wyzwaniom?"},"content":{"rendered":"\n<p>W dobie wszechobecnych stron i aplikacji wydajno\u015b\u0107 sta\u0142a si\u0119 kluczowym elementem, kt\u00f3ry zapewnia u\u017cytkownikowi doskona\u0142e do\u015bwiadczenie korzystania z systemu. React jest bibliotek\u0105 frontendow\u0105, znan\u0105 ze swojej elastyczno\u015bci oraz wydajno\u015bci. Nale\u017cy jednak pami\u0119ta\u0107, \u017ce wydajno\u015b\u0107 ta zale\u017cy w du\u017cym stopniu od developera, kt\u00f3ry tworzy aplikacje, szczeg\u00f3lnie je\u015bli jest to wi\u0119kszy projekt.<\/p>\n\n\n\n<p>W artykule skupimy si\u0119 nad poznaniem i zrozumieniem wyzwa\u0144 przy tworzeniu aplikacji oraz poznamy sposoby, jak sobie z nimi radzi\u0107.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Dlaczego wydajno\u015b\u0107 jest tak wa\u017cna?<\/strong><\/h2>\n\n\n\n<p>Jak ju\u017c wspomnia\u0142em, wydajno\u015b\u0107 wp\u0142ywa na do\u015bwiadczenie u\u017cytkownika korzystaj\u0105cego z naszej aplikacji. Wyobra\u017amy sobie sytuacj\u0119,&nbsp;\u017ce wchodzimy na stron\u0119, gdzie przeliczamy spory pakiet danych i aktualizujemy je co jaki\u015b czas. Zbyt d\u0142ugie oczekiwanie na wynik, lub ewentualnie crash, mo\u017ce spowodowa\u0107, \u017ce u\u017cytkownik wi\u0119cej nie skorzysta z naszego rozwi\u0105zania.<\/p>\n\n\n\n<p>Ponadto, aspekty szybko\u015bci \u0142adowania strony maj\u0105 bezpo\u015bredni wp\u0142yw na SEO (warto wspomnie\u0107, pisz\u0105c artyku\u0142 o React, \u017ce biblioteka ta nie jest najlepszym wyborem z punktu widzenia SEO). Dlatego kwestia wydajno\u015bci jest nie tylko kwesti\u0105 techniczn\u0105, z kt\u00f3r\u0105 my \u2013 programi\u015bci \u2013 musimy sobie radzi\u0107. Jest r\u00f3wnie\u017c kluczow\u0105 kwesti\u0105 dla biznesu, kt\u00f3ry na ko\u0144cu weryfikuje rentowno\u015b\u0107 przedsi\u0119wzi\u0119cia na bazie konwersji.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Wyzwania zwi\u0105zane z wydajno\u015bci\u0105 w React<\/strong><\/h2>\n\n\n\n<p>Jakie s\u0105 podstawowe wyzwania zwi\u0105zane z wydajno\u015bci\u0105&nbsp;w React? Przede wszystkim:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>re-rendering, nadmierny lub nieoptymalny rendering komponent\u00f3w mo\u017ce mie\u0107 wp\u0142yw na pr\u0119dko\u015b\u0107 aplikacji, zw\u0142aszcza je\u015bli pracujemy na du\u017cych danych;<\/li>\n\n\n\n<li>wi\u0119kszy rozmiar paczek pobieranych przez u\u017cytkownika wyd\u0142u\u017ca czas \u0142adowania strony;<\/li>\n\n\n\n<li>wirtualizacja d\u0142u\u017cszych list;<\/li>\n\n\n\n<li>u\u017cywanie atrybutu key, gdzie jest to potrzebne;<\/li>\n\n\n\n<li>kompresja zdj\u0119\u0107.<\/li>\n<\/ul>\n\n\n\n<p>Do tej listy doda\u0107 mo\u017cna wiele innych, mniejszych element\u00f3w, kt\u00f3re postaram si\u0119 przybli\u017cy\u0107 w poni\u017cszym artykule. A wi\u0119c zacznijmy od poznania pierwszej kwestii, kt\u00f3r\u0105 jest\u2026<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Memoizacja<\/strong><\/h2>\n\n\n\n<p>Kluczow\u0105 kwesti\u0105, na kt\u00f3r\u0105 mamy wp\u0142yw, tworz\u0105c aplikacje z u\u017cyciem React, jest memoizacja. Memoizacja w React to technika optymalizacyjna polegaj\u0105ca na zapami\u0119tywaniu wynik\u00f3w drogich w obliczeniu funkcji lub renderowania komponent\u00f3w, aby unikn\u0105\u0107 niepotrzebnego powtarzania tych operacji przy kolejnych renderowaniach.<\/p>\n\n\n\n<p>Na szcz\u0119\u015bcie React dostarcza nam gotowe narz\u0119dzia, aby poradzi\u0107 sobie z tym problemem. Naszym zadaniem jest korzystanie z tych narz\u0119dzi, aby od samego pocz\u0105tku dba\u0107 o kontrolowany re-rendering naszych komponent\u00f3w. Tymi narz\u0119dziami s\u0105:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>React.memo<\/strong><\/h3>\n\n\n\n<p>React.memo to metoda dostarczona bezpo\u015brednio w bibliotece React, kt\u00f3ra otacza przekazany do metody komponent i zapobiega jego niepotrzebnemu ponownemu renderowaniu, gdy jego propsy nie zmieniaj\u0105 si\u0119. Dzia\u0142a przez por\u00f3wnanie poprzednich i aktualnych props\u00f3w, a wykonuje renderowanie tylko wtedy, gdy wykryje zmiany.<\/p>\n\n\n\n<p>W momencie, kiedy mamy do czynienia z komponentami o du\u017cej ilo\u015bci oblicze\u0144 lub li\u015bcie wielu element\u00f3w, mo\u017ce mie\u0107 to spory wp\u0142yw na pr\u0119dko\u015b\u0107 dzia\u0142ania aplikacji, z uwagi na to, \u017ce pozbywamy si\u0119\u00a0ponownego re-renderu kiedy nie\u00a0jest on potrzebny. Poni\u017cej znajdziemy przyk\u0142ad u\u017cycia memo.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz1-1.png\"><img decoding=\"async\" width=\"442\" height=\"437\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz1-1.png\" alt=\"fragment kodu\" class=\"wp-image-26954\" style=\"object-fit:cover\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz1-1.png 442w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz1-1-300x297.png 300w\" sizes=\"(max-width: 442px) 100vw, 442px\" \/><\/a><\/figure>\n\n\n\n<p>Na wy\u017cej za\u0142\u0105czonym przyk\u0142adzie widzimy 2 komponenty<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Users,<\/strong> kt\u00f3ry generuje list\u0119 na bazie otrzymanej tablicy,<\/li>\n\n\n\n<li><strong>App<\/strong>, kt\u00f3ra zawiera stan <strong>counter<\/strong> oraz komponent Users.<\/li>\n<\/ul>\n\n\n\n<p>Dzi\u0119ki rapowaniu komponentu Users przez <strong>memo<\/strong>, ka\u017cdy update stanu counter w komponencie App nie spowoduje renderu listy, poniewa\u017c lista ta si\u0119 nie zmienia. W innym przypadku komponent za ka\u017cdym razem inicjalizowa\u0142by si\u0119 na nowo.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>UseMemo<\/strong><\/h3>\n\n\n\n<p>B\u0119d\u0105c ju\u017c przy React.memo, wspomnijmy o hooku useMemo. Ca\u0142y mechanizm jest tutaj do\u015b\u0107 podobny, lecz w tym przypadku obserwujemy zmiany, jakie zachodz\u0105 w zmiennej, a nie w komponencie.<\/p>\n\n\n\n<p>Mo\u017ce by\u0107 to przydatne, kiedy np. mamy komponent, kt\u00f3ry wy\u015bwietla informacje o u\u017cytkowniku, a jedna z tych danych wymaga do\u015b\u0107 skomplikowanej kalkulacji. Dzi\u0119ki useMemo mo\u017cemy j\u0105 zapami\u0119ta\u0107. Je\u017celi nie zmieni\u0105 si\u0119 parametry, kt\u00f3re wska\u017cemy w tablicy zale\u017cno\u015bci, zapami\u0119tana poprzednio warto\u015b\u0107 zostanie zwr\u00f3cona bez ponownej kalkulacji.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz2.png\"><img decoding=\"async\" width=\"532\" height=\"452\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz2.png\" alt=\"fragment kodu\" class=\"wp-image-26956\" style=\"object-fit:cover\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz2.png 532w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz2-300x255.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz2-400x340.png 400w\" sizes=\"(max-width: 532px) 100vw, 532px\" \/><\/a><\/figure>\n\n\n\n<p>W za\u0142\u0105czonym przyk\u0142adzie kodu prezentujemy informacje o u\u017cytkowniku, w tym status aktywno\u015bci jego konta oraz wynik skomplikowanej kalkulacji zale\u017cnej od stanu konta, kt\u00f3ra wymaga znacznego czasu oblicze\u0144.<\/p>\n\n\n\n<p>Aby unikn\u0105\u0107 powtarzania kodu, przedstawiamy dwa podej\u015bcia do oblicze\u0144:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>standardowe,<\/li>\n\n\n\n<li>wykorzystuj\u0105ce <strong>useMemo<\/strong>.<\/li>\n<\/ul>\n\n\n\n<p>Gdy u\u017cytkownik zmienia status aktywno\u015bci konta poprzez klikni\u0119cie przycisku, nie chcemy ponownie przelicza\u0107 zmiennej <strong>calculation<\/strong>, je\u015bli zmienna <strong>userMoney<\/strong> pozostaje niezmieniona, gdy\u017c wynik oblicze\u0144 pozostanie taki sam.<\/p>\n\n\n\n<p>W tradycyjnym podej\u015bciu warto\u015b\u0107 ta jest niepotrzebnie przeliczana za ka\u017cdym razem, co wyd\u0142u\u017ca czas ponownego renderowania. Natomiast dzi\u0119ki <strong>useMemo<\/strong>, warto\u015b\u0107 ta jest obliczana tylko raz i je\u015bli \u017caden z parametr\u00f3w przekazanych do tablicy zale\u017cno\u015bci si\u0119 nie zmienia, React u\u017cywa zapami\u0119tanej warto\u015bci bez ponownego wywo\u0142ywania kosztownej funkcji <strong>somePowerfulMoneyCalculation<\/strong>.<\/p>\n\n\n\n<p>Efekt u\u017cycia obu podej\u015b\u0107 jest zilustrowany na do\u0142\u0105czonych obrazkach:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Nagrywanie2024-02-07160815-ezgif.com-video-to-gif-converter.gif\"><img decoding=\"async\" width=\"136\" height=\"150\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Nagrywanie2024-02-07160815-ezgif.com-video-to-gif-converter.gif\" alt=\"Efekt zastosowania podej\u015bcia wykorzystuj\u0105cego useMemo \" class=\"wp-image-26966\"\/><\/a><figcaption class=\"wp-element-caption\">Ryc. 1 Efekt zastosowania podej\u015bcia wykorzystuj\u0105cego useMemo<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"140\" height=\"152\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Nagrywanie2024-02-07160856-ezgif.com-video-to-gif-converter-1.gif\" alt=\"Efekt zastosowania podej\u015bcia  bez  u\u017cycia useMemo\" class=\"wp-image-26968\"\/><figcaption class=\"wp-element-caption\">Ryc. 2 Efekt zastosowania podej\u015bcia  bez  u\u017cycia useMemo<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>useCallback<\/strong><\/h3>\n\n\n\n<p>Ostatnim narz\u0119dziem do memoizacji w React jest hook useCallback, kt\u00f3ry s\u0142u\u017cy do zapami\u0119tywania definicji funkcji. Zasada u\u017cycia useCallback jest analogiczna do useMemo: jako pierwszy parametr przekazujemy funkcj\u0119, kt\u00f3ra ma zosta\u0107 zapami\u0119tana, a drugi to tablica zale\u017cno\u015bci, kt\u00f3re wskazuje po zmianie jakich parametr\u00f3w ma na nowo zdefiniowa\u0107 i zapami\u0119ta\u0107 funkcj\u0119.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz3.png\"><img decoding=\"async\" width=\"457\" height=\"449\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz3.png\" alt=\"fragment kodu\" class=\"wp-image-26960\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz3.png 457w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz3-300x295.png 300w\" sizes=\"(max-width: 457px) 100vw, 457px\" \/><\/a><\/figure>\n\n\n\n<p>W przedstawionym fragmencie kodu znajduje si\u0119 ma\u0142y formularz, kt\u00f3ry po naci\u015bni\u0119ciu przycisku \u201eSend\u201d wysy\u0142a dane do backendu. Gdy w kodzie wykorzystujemy hook <strong>useCallback<\/strong>, nasza funkcja wysy\u0142aj\u0105ca dane jest zdefiniowana tylko raz i zostaje zapami\u0119tana, co jest efektywne, gdy\u017c nie ma potrzeby jej wielokrotnej definicji.<\/p>\n\n\n\n<p>Z drugiej strony, je\u015bli usuniemy <strong>useCallback<\/strong>, funkcja ta b\u0119dzie definiowana ponownie za ka\u017cdym razem, gdy nast\u0105pi zmiana stanu formularza, na przyk\u0142ad zmiany warto\u015bci zmiennej <strong>someFlag<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Lazy loading<\/strong><\/h2>\n\n\n\n<p>Na pocz\u0105tku rozwoju nowego projektu, warto zatrzyma\u0107 si\u0119 na chwil\u0119 i przemy\u015ble\u0107, jak du\u017ca b\u0119dzie nasza aplikacja i czy wszystkie jej elementy oraz modu\u0142y b\u0119d\u0105 nam potrzebne od razu. Je\u015bli nie, warto zastanowi\u0107 si\u0119&nbsp;nad lazy loadingiem. Jest to spos\u00f3b na stopniowe \u0142adowanie modu\u0142\u00f3w aplikacji wtedy, kiedy b\u0119d\u0105 nam one potrzebne. Oznacza to w praktyce, \u017ce je\u015bli u\u017cytkownik nie wejdzie w np.: podstron\u0119 subskrypcja, kod do tego modu\u0142u nie zostanie zaci\u0105gni\u0119ty do naszej aplikacji, co ma bezpo\u015bredni wp\u0142yw na \u0142adowanie aplikacji.<\/p>\n\n\n\n<p>Lazy loading mo\u017cemy w bardzo prosty spos\u00f3b zaimplementowa\u0107 do naszej aplikacji. B\u0119dzie nam do tego potrzebna metoda <strong>lazy,<\/strong> kt\u00f3ra dostarczana jest przez React, oraz po\u0142\u0105czenie jej z komponentem <strong>Suspence<\/strong>, pozwalaj\u0105cym okre\u015bli\u0107 zachowanie aplikacji podczas \u0142adowania modu\u0142u.<\/p>\n\n\n\n<p>Przyk\u0142adowy fragment kodu:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz4.png\"><img decoding=\"async\" width=\"602\" height=\"349\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz4.png\" alt=\"fragment kodu\" class=\"wp-image-26962\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz4.png 602w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz4-300x174.png 300w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/figure>\n\n\n\n<p>W tym kodzie implementujemy routing po\u0142\u0105czony z lazy loadingiem. Dzi\u0119ki temu, w zale\u017cno\u015bci od tego, na jakiej stronie si\u0119 znajdujemy, pozosta\u0142e podstrony (czyli ich komponenty) b\u0119d\u0105 \u0142adowane w momencie wej\u015bcia w konkretny link. Ca\u0142y proces \u0142adowania tzw. chunk\u00f3w widoczny b\u0119dzie w sekcji network w devtools jako kolejna, dodatkowa paczka kodu js.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Wirtualizacja<\/strong><\/h2>\n\n\n\n<p>Ka\u017cdy z nas na pewno mia\u0142 kiedy\u015b styczno\u015b\u0107 z listami, tabelkami lub innymi komponentami, kt\u00f3re wy\u015bwietli\u0107 mia\u0142y X element\u00f3w. W przypadku, gdy obs\u0142ugujemy paginacje, nie ma z tym problemu \u2013 mo\u017cemy pobiera\u0107 strona po stronie dane i nie grozi nam problem z obci\u0105\u017ceniem aplikacji. Czasem jednak celem jest np.: infinity scroll, jak na Facebooku, kt\u00f3ry pozwala nam \u0142adowa\u0107 nowe posty ca\u0142y czas oraz wr\u00f3ci\u0107 do tych, kt\u00f3re pobrali\u015bmy par\u0119 sekund temu (a czasem nawet minut, jak kto\u015b si\u0119 zasiedzi).<\/p>\n\n\n\n<p>Pytanie, jakie nale\u017cy postawi\u0107, to: w jaki spos\u00f3b jeste\u015bmy w stanie wy\u015bwietli\u0107 np. 10 000 element\u00f3w i dalej zapewni\u0107&nbsp;p\u0142ynno\u015b\u0107 dzia\u0142ania aplikacji?<\/p>\n\n\n\n<p>Aby poradzi\u0107 sobie z tym problemem, przytocz\u0119 temat wirtualizacji. Polega ona na dynamicznym \u0142adowaniu i renderowaniu tylko tych cz\u0119\u015bci danych, kt\u00f3re aktualnie s\u0105 widoczne dla u\u017cytkownika. Efektem jest zmniejszona ilo\u015b\u0107 element\u00f3w w DOM w danym momencie i wi\u0119ksza p\u0142ynno\u015b\u0107 naszej aplikacji.<\/p>\n\n\n\n<p>Aby w prosty spos\u00f3b zaimplementowa\u0107 mechanizm wirtualizacji w naszej aplikacji, skorzysta\u0107 mo\u017cemy z zewn\u0119trznej biblioteki o nazwie <strong>react-window<\/strong>. Jej u\u017cycie jest bardzo proste i ju\u017c po kilku chwilach mo\u017cemy zobaczy\u0107 zalety korzystania z wirtualizacji.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz5.png\"><img decoding=\"async\" width=\"602\" height=\"315\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz5.png\" alt=\"fragment kodu\" class=\"wp-image-26964\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz5.png 602w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz5-300x157.png 300w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/image8.gif\"><img decoding=\"async\" width=\"356\" height=\"194\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/image8.gif\" alt=\"Zastosowanie wirtualizacji\" class=\"wp-image-26973\"\/><\/a><figcaption class=\"wp-element-caption\">Ryc. 3 Zastosowanie wirtualizacji<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Key<\/strong><\/h2>\n\n\n\n<p>Kolejnym aspektem, kt\u00f3ry mo\u017ce zwi\u0119kszy\u0107 wydajno\u015b\u0107 strony, kiedy renderujemy list\u0119, jest property <strong>key<\/strong>. React u\u017cywa tej w\u0142a\u015bciwo\u015bci do \u015bledzenia, kt\u00f3re elementy si\u0119 zmieni\u0142y, co jest szczeg\u00f3lnie wa\u017cne przy aktualizacji stanu. Bez unikalnego (to wa\u017cne) property <strong>key<\/strong>, React mo\u017ce nieprawid\u0142owo odtworzy\u0107 i zaktualizowa\u0107 elementy na li\u015bcie, co prowadzi do nieefektywnego i b\u0142\u0119dnego dzia\u0142ania aplikacji.<\/p>\n\n\n\n<p>Pos\u0142u\u017cmy si\u0119 przyk\u0142adem: mamy list\u0119 2 element\u00f3w, lecz wyobra\u017amy sobie, \u017ce ta lista jest du\u017co d\u0142u\u017csza. Przy mapowaniu element\u00f3w, ka\u017cdy element powinien mie\u0107 swoj\u0105 unikaln\u0105 warto\u015b\u0107 key (nie nale\u017cy stosowa\u0107 indexu listy). Dobrym pomys\u0142em jest wykorzystanie jako warto\u015bci key, ID u\u017cytkownika, kt\u00f3re, jak samo zastosowanie wskazuje, powinna by\u0107 unikalne.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz6.png\"><img decoding=\"async\" width=\"602\" height=\"435\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz6.png\" alt=\"fragment kodu\" class=\"wp-image-26975\" style=\"object-fit:cover\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz6.png 602w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Obraz6-300x217.png 300w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/figure>\n\n\n\n<p>W powy\u017cszym kodzie nale\u017cy r\u00f3wnie\u017c zauwa\u017cy\u0107, \u017ce mamy metod\u0119, kt\u00f3rej zadaniem jest usuni\u0119cie konkretnego u\u017cytkownika z naszej listy. Bez w\u0142a\u015bciwego u\u017cycia key (np. poprzez index listy), React mia\u0142by spory problem na identyfikacj\u0119, kt\u00f3re elementy zosta\u0142y usuni\u0119te, a kt\u00f3re powinny zosta\u0107.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Throttling i debouncing<\/strong><\/h2>\n\n\n\n<p>Obie techniki s\u0142u\u017c\u0105 do wywo\u0142a\u0144 funkcji w odpowiedzi na zdarzenia w naszym systemie. W skr\u00f3cie:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Throttling<\/strong> \u2013 polega na ograniczeniu liczby wywo\u0142a\u0144 funkcji do jednego w okre\u015blonym interwale czasowym. Jest to przydatne m.in.: przy \u015bledzeniu zdarze\u0144 przewijania, aby unikn\u0105\u0107 nadmiernego obci\u0105\u017cenia. Znaczy to, \u017ce je\u015bli ustawimy interwa\u0142 na 1s przy evencie scroll, metoda ta, mimo dalszego scrollowania, zostanie wywo\u0142ana dopiero po up\u0142ywie 1s.<\/li>\n\n\n\n<li><strong>Debouncing<\/strong> \u2013 polega na od\u0142o\u017ceniu wykonania funkcji do momentu, gdy przestan\u0105 nap\u0142ywa\u0107 nowe zdarzenia przez okre\u015blony czas. Jest to przydatne, na przyk\u0142ad, przy wyszukiwaniu w czasie rzeczywistym, gdy chcemy op\u00f3\u017ani\u0107 zapytanie do serwera do momentu, gdy u\u017cytkownik sko\u0144czy pisa\u0107 na klawiaturze.<\/li>\n<\/ul>\n\n\n\n<p>Obie te metody dost\u0119pne s\u0105 np. w bibliotece lodash.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Kompresja zdj\u0119\u0107<\/strong><\/h2>\n\n\n\n<p>Niezale\u017cnie od tego, czy u\u017cywamy React, Angular, Vue, czy te\u017c piszemy w czystym stacku HTML\/CSS\/JS, \u0142adowanie zdj\u0119\u0107 prawie w ka\u017cdej aplikacji wygl\u0105da\u0107 b\u0119dzie tak samo. Aby zapewni\u0107 szybkie \u0142adowanie plik\u00f3w z serwera, warto kompresowa\u0107 wszystkie zdj\u0119cia i ikony na naszej stronie. W ten spos\u00f3b jeste\u015bmy w stanie zmniejszy\u0107 rozmiar plik\u00f3w niekiedy nawet o 90%.<\/p>\n\n\n\n<p>Przydatnymi narz\u0119dziami do kompresji mog\u0105 by\u0107 np. tinypng lub svgomg.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Podsumowanie<\/strong><\/h2>\n\n\n\n<p>Jak wida\u0107, mamy sporo mo\u017cliwo\u015bci na optymalizacj\u0119 naszych aplikacji. W tym artykule przedstawi\u0142em kilka z nich, lecz lista mo\u017ce by\u0107 znacznie d\u0142u\u017csza.<\/p>\n\n\n\n<p>Przed startem ka\u017cdego projektu warto zatrzyma\u0107 si\u0119 na chwil\u0119 i zastanowi\u0107 m.in.:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>jak du\u017cy b\u0119dzie to projekt,<\/li>\n\n\n\n<li>co b\u0119dzie zawiera\u0142,<\/li>\n\n\n\n<li>czy musimy wszystkie modu\u0142y \u0142adowa\u0107 na raz,<\/li>\n\n\n\n<li>w jaki spos\u00f3b b\u0119d\u0119 zarz\u0105dza\u0107 stanem w aplikacji i wiele innych.<\/li>\n<\/ul>\n\n\n\n<p>Pozwoli nam to zaplanowa\u0107 mechanizmy i regu\u0142y, kt\u00f3re wespr\u0105 optymalizacj\u0119 aplikacji, zanim b\u0119dzie za p\u00f3\u017ano.<\/p>\n\n\n\n<p>***<\/p>\n\n\n\n<p>Je\u015bli interesuje Ci\u0119 temat React, sprawd\u017a r\u00f3wnie\u017c <a href=\"https:\/\/sii.pl\/blog\/wyszukiwarka\/react\/\" target=\"_blank\" aria-label=\"inne artyku\u0142y naszych ekspert\u00f3w (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\">inne artyku\u0142y naszych ekspert\u00f3w<\/a>. <\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;26953&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;5&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;5&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;5\\\/5 ( votes: 5)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;Wydajno\u015b\u0107 w aplikacjach React \u2013 jak sprosta\u0107 wyzwaniom?&quot;,&quot;width&quot;:&quot;139.5&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 139.5px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            5\/5 ( votes: 5)    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>W dobie wszechobecnych stron i aplikacji wydajno\u015b\u0107 sta\u0142a si\u0119 kluczowym elementem, kt\u00f3ry zapewnia u\u017cytkownikowi doskona\u0142e do\u015bwiadczenie korzystania z systemu. React &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/wydajnosc-w-aplikacjach-react-jak-sprostac-wyzwaniom\/\">Continued<\/a><\/p>\n","protected":false},"author":486,"featured_media":26979,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1314],"tags":[2427,1546,1512,991],"class_list":["post-26953","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development-na-twardo","tag-digital","tag-przeglad-narzedzi","tag-poradnik","tag-react"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/02\/Wydajnosc-w-aplikacjach-React-\u2013-jak-sprostac-wyzwaniom.jpg","category_names":["Development na twardo"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/26953"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/users\/486"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/comments?post=26953"}],"version-history":[{"count":3,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/26953\/revisions"}],"predecessor-version":[{"id":26981,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/26953\/revisions\/26981"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media\/26979"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media?parent=26953"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/categories?post=26953"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/tags?post=26953"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}