⊗jsrtPmHkUCb 16 of 47 menu

Хук за оптимизация на производителността useCallback в React

В този урок ще разгледаме следващия хук за оптимизация на производителността useCallback.

Хукът useCallback е подобен на API useMemo, разликата е, че първият кешира стойност между моментите на прерисуване на екрана, а вторият - callback функция. Това ни позволява да не презапускаме ресурсоемките функции, когато не е необходимо и може да се използва при предаване на функция в дъщерни компоненти.

Нека разберем по-подробно с пример. Първо създаваме компонент App и създаваме в него състояние num:

const [num, setNum] = useState(0);

Нека имаме бутон, при клик върху който num се увеличава с 1, и параграф, в който ще извеждаме стойността на num:

return ( <div> <button onClick={() => setNum(num + 1)}>click</button> <p>clicks: {num}</p> </div> );

А сега, да предположим, че в App се извежда и някакъв списък с елементи, който ще допълваме при натискане на друг бутон. За съхранение на елементите от този списък ще създадем състояние items:

const [items, setItems] = useState([]);

И след това ще напишем функция addItem за тяхното добавяне:

function addItem() { setItems([...items, 'new item']); }

Сега нека напишем код за показване на елементите от списъка и да го изнесем в дъщерен компонент Items, който като пропсове ще получава масив от елементи и функция за тяхното добавяне. Да не забравим да добавим извеждане в конзолата, за да виждаме кога нашият Items ще се прерисува:

function Items({ items, addItem }) { const result = items.map((item, index) => { return <p key={index}>{item}</p>; }); console.log('Items render'); return ( <div> <h3>Our items</h3> {result} <button onClick={addItem}>add item</button> </div> ); } export default Items;

Разполагаме Items в края на компонента App и ще му предаваме масива items и функцията за добавяне на елементи addItem:

return ( <> <div> <button onClick={() => setNum(num + 1)}>click</button> <p>clicks: {num}</p> <br /> </div> <Items items={items} addItem={addItem} /> </> );

А сега да натиснем бутоните и да се убедим, че num расте и нови елементи се добавят в списъка. А като отворим конзолата, ще видим, че нашият списък се прерисува всеки път, дори и да кликваме върху бутона, който увеличава num.

Ако имаме малък списък, тогава всичко е наред, а ако се предполага, че той ще е обемен и има още много неща там? Няма проблем - ще кажете, защото в предишния урок разгледахме API memo, за да избегнем ненужни прерисувания на компонента.

Така че нека обвием нашия компонент Items в memo и всичко е готово. Между другото това може да се направи директно при експорт на Items:

export default memo(Items);

Да не забравим да импортираме memo:

import { memo } from 'react';

А сега отваряме конзолата и натискаме бутоните. Всички усилия напразно! Ние мемоизирахме компонента, но при натискане на бутона 'click' компонентът Items все пак се прерисува всеки път.

Работата е там, че когато родителският компонент се прерисува, неговите функции се пресъздават наново - това се отнася и за нашата функция addItem, която предаваме в Items.

Точно в този момент ще ни помогне хукът useCallback. Нека го приложим. Първо го импортираме в App:

import { useCallback } from 'react';

След това преработваме простото деклариране на функцията addItem в Function Expression, посочваме като първи параметър за useCallback нашата функция под формата на callback. Вторият параметър в квадратни скоби посочваме зависимостите - всички реактивни променливи, участващи във функцията, в нашия случай това е масивът items:

const addItem = useCallback(() => { setItems(() => [...items, 'New item']); }, [items]);

Готово! По този начин ние кеширахме функцията. Натискаме отново бутоните и виждаме, че сега при натискане на бутона 'click' нашият дъщерен компонент не се прерисува.

Създайте компонент App, поставете в него параграф с текст. Създайте състояние с начална стойност 'text' и я изведете в параграфа. Нека при клик върху параграфа в края на текста му се добавя удивителен знак.

Създайте дъщерен компонент Products, в който ще имате бутон за добавяне на нов продукт. Разположете го в App. В родителския компонент създайте състояние с масив от продукти и функция за добавяне на нов продукт. Предайте ги в качеството на пропсове в дъщерния, изведете в него предадения масив като списък ul.

В Products изведете в конзолата текст 'products render'. Обвийте Products в memo. Кликнете върху параграфа и бутона. Уверете се, че при клик върху параграфа дъщерният компонент все пак се прерисува.

Кеширайте функцията за добавяне на продукти, като я обвиете в хука useCallback. Кликнете върху параграфа и бутона. Уверете се, че при клик върху параграфа, дъщерният компонент вече не се прерисува.

Български
AfrikaansAzərbaycanবাংলাБеларускаяČeštinaDanskDeutschΕλληνικάEnglishEspañolEestiSuomiFrançaisहिन्दीMagyarՀայերենIndonesiaItaliano日本語ქართულიҚазақ한국어КыргызчаLietuviųLatviešuМакедонскиMelayuမြန်မာNederlandsNorskPolskiPortuguêsRomânăРусскийසිංහලSlovenčinaSlovenščinaShqipСрпскиSrpskiSvenskaKiswahiliТоҷикӣไทยTürkmenTürkçeЎзбекOʻzbekTiếng Việt
Ние използваме бисквитки за работата на сайта, анализ и персонализация. Обработката на данни се извършва в съответствие с Политика за поверителност.
приемам всички настройки отхвърляне