Хук аптымізацыі прадукцыйнасці useCallback у React
У гэтым уроку мы разгледзім наступны
хук для аптымізацыі прадукцыйнасці
useCallback.
Хук useCallback падобны да API useMemo,
адрозненне заключаецца ў тым, што першы
кэшуе значэнне паміж маментамі перамалёўкі
экрана, а другі - колбэк.
Гэта дазваляе нам не перазапускаць рэсурсазатратныя
функцыі, калі гэта не патрабуецца і можа
выкарыстоўвацца пры
перадачы функцыі
у даччыныя кампаненты.
Давайце разбярэмся падрабязней на прыкладзе.
Для пачатку створым кампанент 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([]);
І затым напiшам функцыю addItem
для іх дадавання:
function addItem() {
setItems([...items, 'new item']);
}
Цяпер давайце напiшам код для адлюстравання
элементаў спісу і вынясем яго ў даччыны
кампанент 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
нашу функцыю ў выглядзе колбэка. Другім
параметрам у квадратных дужках пакажам
залежнасці - усе рэактыўныя зменныя,
якія ўдзельнічаюць у функцыі, у нашым выпадку
гэта масіў items:
const addItem = useCallback(() => {
setItems(() => [...items, 'New item']);
}, [items]);
Гатова! Такім чынам мы закэшавалі
функцыю. Націскаем зноў на кнопачкі і
бачым, што цяпер пры націску на кнопку
'click' наш даччыны кампанент не
перамалёўваецца.
Стварыце кампанент App, змясціце
ў яго абзац з тэкстам. Завядзіце
стейт з пачатковым значэннем 'text'
і вывядзіце яго ў абзацы. Хай па кліку
на абзац яму ў канец тэксту
дадаецца клічнік.
Стварыце даччыны кампанент Products,
у якім у вас будзе кнопка для дадавання
новага прадукту. Размясціце яго ў App.
У бацькоўскім кампаненце стварыце стэйт
з масівам прадуктаў і функцыю дадавання
новага прадукту. Перадайце іх у
якасці пропсаў у даччыны, вывядзіце ў ім
перададзены масіў у выглядзе спісу ul.
У Products вывядзіце ў кансоль тэкст
'products render'.
Аберыце Products у memo.
Паклікайце на абзац і кнопку. Пераканайцеся,
што пры кліку на абзац даччыны кампанент
усё роўна перамалёўваецца.
Закэшавайце функцыю для дадавання
прадуктаў, абернуўшы яе ў хук useCallback.
Паклікайце на абзац і кнопку. Пераканайцеся,
што пры кліку на абзац, даччыны кампанент
больш не перамалёўваецца.