Хук за оптимизацију перформанси useCallback у React-у
У овом лекцији ћемо размотрити следећи
хук за оптимизацију перформанси
useCallback.
Хук useCallback је сличан API-ју useMemo,
разлика је у томе што први
кешира вредност између тренутака поновног исцртавања
екрана, а други - callback.
Ово нам омогућава да не покрећемо поново ресурсно захтевне
функције када то није потребно и може
се користити приликом
прослеђивања функције
у компоненте детета.
Хајде да детаљније размотримо на примеру.
Прво, направимо компонент App
и у њему креирајмо state num:
const [num, setNum] = useState(0);
Нека имамо дугме, при клику
на које се num повећава
за 1, и пасус у коме ћемо
исписати вредност num:
return (
<div>
<button onClick={() => setNum(num + 1)}>кликни</button>
<p>кликова: {num}</p>
</div>
);
Сада, претпоставимо да у
App имамо још један приказ
листе са ставкама, коју ћемо допуњавати
притиском на друго дугме. За чување
ставки ове листе креирајмо
state items:
const [items, setItems] = useState([]);
Затим напишимо функцију addItem
за њихово додавање:
function addItem() {
setItems([...items, 'нова ставка']);
}
Хајде сада да напишемо код за приказ
ставки листе и да га издвојимо у компонент дете
Items, који ће у виду
пропсова добијати низ ставки
и функцију за њихово додавање. Не заборавимо
да додамо испис у конзолу, да бисмо видели
када ће се наш Items
поново исцртати:
function Items({ items, addItem }) {
const result = items.map((item, index) => {
return <p key={index}>{item}</p>;
});
console.log('Items се исцртава');
return (
<div>
<h3>Наше ставке</h3>
{result}
<button onClick={addItem}>додај ставку</button>
</div>
);
}
export default Items;
Поставимо Items на крај компонента
App и проследимо му низ
items и функцију за додавање
ставки addItem:
return (
<>
<div>
<button onClick={() => setNum(num + 1)}>кликни</button>
<p>кликова: {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';
Сада отворимо конзолу и кликнимо
на дугмад. Свa trud је узалуд! Ми
смо мемоизирали компонент, али при притиску
на дугме 'кликни' компонента
Items се и даље
понио исцртава сваки пут.
Ствар је у томе што када се родитељска
компонента поново исцртава, њене функције
се поново креирају - то се односи и на нашу
функцију addItem, коју прослеђујемо у
Items.
Управо у овом тренутку ће нам помоћи хук
useCallback. Хајде да га применимо.
Прво, увезимо га у
App:
import { useCallback } from 'react';
Затим преправимо једноставно декларисање функције
addItem у
Function Expression, наведемо као
први параметар за useCallback
нашу функцију у виду callback-а. Другим
параметром у угаоним заградама наведемо
зависности - све реактивне променљиве
које учествују у функцији, у нашем случају
то је низ items:
const addItem = useCallback(() => {
setItems(() => [...items, 'Нова ставка']);
}, [items]);
Готово! На овај начин смо кеширали
функцију. Поново кликнимо на дугмад и
видимо да сада при притиску на дугме
'кликни' наша компонента дете не
поново се исцртава.
Направите компонент App, поставите
у њега пасус са текстом. Креирајте
state са почетном вредношћу 'текст'
и испишите га у пасусу. Нека се при клику
на пасус његовом тексту
додаје узвичник.
Направите компонент дете Products,
у којем ћете имати дугме за додавање
новог производа. Поставите га у App.
У родитељској компоненти креирајте state
са низом производа и функцију за додавање
новог производа. Проследите их у
компонент дете као пропсове, испишите у њему
прослеђени низ у виду листе ul.
У Products испишите у конзолу текст
'products се исцртава'.
Омотајте Products у memo.
Кликните на пасус и дугме. Уверите се
да при клику на пасус компонента дете
и даље се поново исцртава.
Кеширајте функцију за додавање
производа, обавијајући је у хук useCallback.
Кликните на пасус и дугме. Уверите се
да при клику на пасус, компонента дете
више не понавља исцртавање.