Мемоизација је техника оптимизације, слична кеширању. Функционише тако што чува претходне резултате позива функције и користи те резултате следећи пут када се функција покрене. Посебно је користан у апликацијама које су тешке за рачунање и које понављају позиве функција на истим параметрима.
Мемоизацију можете да користите у обичном ЈаваСцрипт-у и такође у Реацт-у, на неколико различитих начина.
Мемоизација у ЈаваСцрипт-у
Да бисте меморисали функцију у ЈаваСцрипт-у, морате да сачувате резултате те функције у кеш меморији. Кеш може бити објекат са аргументима као кључевима и резултатима као вредностима.
Када позовете ову функцију, она прво проверава да ли је резултат присутан у кешу пре покретања. Ако јесте, враћа кеширане резултате. У супротном, извршава се.
Размотрите ову функцију:
функцијаквадрат(бр) {
повратак број * бр
}
Функција узима аргумент и враћа његов квадрат.
Да бисте покренули функцију, позовите је са бројем попут овог:
квадрат(5) // 25
Са 5 као аргументом, скуаре() ће радити прилично брзо. Међутим, ако бисте израчунали квадрат од 70.000, дошло би до значајног кашњења. Не много, али ипак са кашњењем. Сада, ако бисте позвали функцију више пута и прешли 70.000, искусили бисте кашњење у сваком позиву.
Ово кашњење можете елиминисати користећи меморисање.
конст мемоизедСкуаре = () => {
дозволити цацхе = {};
повратак (број) => {
ако (број у цацхе) {
цонсоле.лог('Поновно коришћење кеширане вредности');
повратак цацхе[бр];
} друго {
цонсоле.лог('Резултат израчунавања');
дозволити резултат = број * број;
// цацхе тхе Новарезултатвредностзаследећивреме
цацхе[бр] = резултат;
повратак резултат;
}
}
}
У овом примеру, функција проверава да ли је раније израчунала резултат тако што проверава да ли постоји у објекту кеша. Ако има, враћа већ израчунату вредност.
Када функција прими нови број, израчунава нову вредност и похрањује резултате у кеш пре него што се врати.
Опет, овај пример је прилично једноставан, али објашњава како би меморисање функционисало да побољша перформансе програма.
Требало би да меморишете само чисте функције. Ове функције враћају исти резултат када проследите исте аргументе. Ако користите меморисање на нечистим функцијама, нећете побољшати перформансе, већ ћете повећати трошкове. То је зато што бирате брзину уместо меморије сваки пут када меморишете функцију.
Мемоизација у Реацт-у
Ако желите да оптимизујете Реацт компоненте, Реацт обезбеђује мемоизацију преко усеМемо() куке, Реацт.мемо и усеЦаллБацк().
Коришћење усеМемо()
усеМемо() је а Реаговати кука који прихвата функцију и низ зависности.
конст мемоизедВалуе = усеМемо(() => цомпутеЕкпенсивеВалуе (а, б), [а, б]);
Он меморише вредност враћену из те функције. Вредности у низу зависности диктирају када се функција извршава. Тек када се промене, функција се поново извршава.
На пример, следећа компонента апликације има меморисану вредност која се зове резултат.
увоз { усеМемо } из "реаговати"
функцијаАпликација(вредност) {
конст квадрат = (вредност) => {
повратак вредност * вредност
}
конст резултат = усеМемо(
() => квадрат (вредност),
[ вредност ]
);
повратак (
<див>{резултат (5)}</div>
)
}
Компонента апликације позива скуаре() на сваком рендеру. Перформансе ће се смањити ако се компонента апликације рендерује много пута због Реацт пропс промена или ажурирање стања, посебно ако је функција скуаре() скупа.
Међутим, пошто усеМемо() кешира враћене вредности, квадратна функција се не извршава при сваком поновном приказивању осим ако се аргументи у низу зависности не промене.
Коришћење Реацт.мемо()
Реацт.мемо() је компонента вишег реда која прихвата Реацт компоненту и функцију као аргументе. Функција одређује када компоненту треба ажурирати.
Функција је опциона и ако није обезбеђена, Реацт.мемо прави плитку копију упоређивања тренутних реквизита компоненте са претходним реквизитима. Ако су реквизити другачији, то покреће ажурирање. Ако су реквизити исти, он прескаче поновно приказивање и поново користи меморисане вредности.
Опциона функција прихвата претходне пропс и следеће пропс као аргументе. Затим можете експлицитно да упоредите ове реквизите да бисте одлучили да ли да ажурирате компоненту или не.
Реаговати.Белешка(Саставни део, [ареЕкуал (превПропс, нектПропс)])
Хајде да прво погледамо пример без опционог аргумента функције. Испод је компонента под називом Коментари која прихвата име и реквизите е-поште.
функцијаКоментари ({име, коментар, свиђања}) {
повратак (
<див>
<стр>{наме}</п>
<стр>{цоммент}</п>
<стр>{свиђа}</п>
</div>
)
}
Компонента меморисаних коментара ће имати Реацт.мемо омотан око ње на следећи начин:
конст МемоизедЦоммент = Реацт.мемо (Коментар)
Можете позвати, а затим је позвати као било коју другу компоненту Реацт-а.
<МемоизедЦоммент наме="Мари" цоммент="Мемоизација је одлична" свиђања=1/>
Ако желите сами да извршите поређење реквизита, проследите следећу функцију у Реацт.мемо као други аргумент.
увоз Реаговати из "реаговати"
функцијацхецкЦомментПропс(превПропс, нектПропс) {
повратак превПропс.наме нектПропс.наме
&& превПропс.цоммент нектПропс.цоммент
&& превПропс.ликес нектПропс.ликес
}
конст МемоизедЦоммент = Реацт.мемо (Коментари, цхецкЦомментПропс)
Ако цхецкПрофилеПропс врати труе, компонента се не ажурира. У супротном, поново се приказује.
Прилагођена функција је корисна када желите да прилагодите поновно приказивање. На пример, можете да га користите за ажурирање компоненте Коментари само када се промени број свиђања.
За разлику од усеМемо() куке која меморише само враћену вредност функције, Реацт.мемо меморише целу функцију.
Користите Реацт.мемо само за чисте компоненте. Такође, да бисте смањили трошкове поређења, запамтите само компоненте чији се реквизити често мењају.
Коришћење усеЦаллБацк()
Можете користити усеЦаллБацк() куку за меморисање компоненте функције.
конст мемоизедЦаллбацк = усеЦаллбацк(
() => {
учинити нешто (а, б);
},
[а, б],
);
Функција се ажурира само када се промене вредности у низу зависности. Закачива ради као повратни позив усеМемо(), али меморише компоненту функције између рендеровања уместо да меморише вредности.
Размотрите следећи пример меморисане функције која позива АПИ.
увоз { усеЦаллбацк, усеЕффецт } из "реаговати";
конст Компонента = () => {
конст гетДата = усеЦаллбацк(() => {
цонсоле.лог('позовите АПИ');
}, []);
усеЕффецт(() => {
гетДата();
}, [гетДата]);
};
Функција гетДата() позвана у усеЕффецт-у биће поново позвана само када се вредност гетДата промени.
Да ли би требало да запамтите?
У овом туторијалу научили сте шта је мемоизација, њене предности и како да је примените у ЈаваСцрипт-у и Реацт-у. Међутим, треба да знате да је Реацт већ брз. У већини случајева меморисање компоненти или вредности додаје трошкове поређења и не побољшава перформансе. Због тога запамтите само скупе компоненте.
Реацт 18 је такође представио нове куке као што су усеИд, усеТранситион и усеИнсертионЕффецт. Можете их користити да побољшате перформансе и корисничко искуство Реацт апликација.