Хук за оптимизација на перформансите useCallback во React
Во оваа лекција ќе го разгледаме следниот
hook за оптимизација на перформансите
useCallback.
Hook-от useCallback е сличен на API-то useMemo,
разликата е во тоа што првиот
кешира вредност помеѓу моментите на прецртување
на екранот, а вториот - callback.
Ова ни овозможува да не рестартираме ресурсно-интензивни
функции кога тоа не е потребно и може
да се користи при
пренос на функција
во детските компоненти.
Ајде да разбереме подетално на пример.
За почеток да креираме компонента App
и да воспоставиме state num во неа:
const [num, setNum] = useState(0);
Нека имаме копче, при клик
на кое num се зголемува
за 1, и параграф, во кој ќе
ја прикажуваме вредноста num:
return (
<div>
<button onClick={() => setNum(num + 1)}>click</button>
<p>clicks: {num}</p>
</div>
);
А сега, да претпоставиме дека во
App се прикажува уште некоја листа
со елементи, која ќе ја дополнуваме
со притискање на друго копче. За чување
на елементите од оваа листа ќе воспоставиме
state items:
const [items, setItems] = useState([]);
И потоа ќе напишеме функција addItem
за нивно додавање:
function addItem() {
setItems([...items, 'new item']);
}
Сега ајде да го напишеме кодот за приказ
на елементите од листата и да го издвоиме во детска
компонента Items, која како
пропертија ќе добие низа од елементи
и функција за нивно додавање. Да не заборавиме
да додадеме print во конзола, за да видиме
кога нашата 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.
Токму во овој момент hook-от
useCallback ќе ни помогне. Ајде да го примениме
него. За почеток да го импортираме во
App:
import { useCallback } from 'react';
Потоа да ја претвориме едноставната декларација на функцијата
addItem во
Function Expression, да наведеме како
прв параметар за useCallback
нашата функција во вид на callback. Вториот
параметар во квадратни загради ќе ги наведеме
зависностите - сите реактивни променливи,
кои учествуваат во функцијата, во нашиот случај
тоа е низата items:
const addItem = useCallback(() => {
setItems(() => [...items, 'New item']);
}, [items]);
Готово! На овој начин ја кеширавме
функцијата. Кликнуваме повторно на копчињата и
гледаме дека сега при притискање на копчето
'click' нашата детска компонента не
се прецртува.
Креирајте компонента App, поставете
во неа параграф со текст. Воспоставете
state со почетна вредност 'text'
и прикажете ја во параграфот. Нека при клик
на параграфот на крајот од текстот
му се додава извичник.
Креирајте детска компонента Products,
во која ќе имате копче за додавање
нов продукт. Поставете ја во App.
Во родителската компонента креирајте state
со низа на производи и функција за додавање
нов продукт. Пренесете ги во
како пропертија во детската, прикажете ја во неа
пренесената низа како листа ul.
Во Products прикажете во конзола текст
'products render'.
Завиткајте ја Products во memo.
Кликнувајте на параграфот и копчето. Уверете се,
дека при клик на параграфот детската компонента
сепак се прецртува.
Закеширајте ја функцијата за додавање
продукти, завиткајќи ја во hook-от useCallback.
Кликнувајте на параграфот и копчето. Уверете се,
дека при клик на параграфот, детската компонента
повеќе не се прецртува.