Application ကြီးလာတာနဲ့အမျှ Performance ပြဿနာက ပိုကြီးလာပါတယ်။ App ရဲ့ Performance ကောင်းဖို့အတွက် React ရဲ့ feature တွေကို မှန်မှန်ကန်ကန် အသုံးချတတ်ဖို့လိုပါတယ်။ အဲဒီ feature တွေထဲက React.useMemo ကို ရှင်းပြချင်ပါတယ်။
useMemo ဆိုတာ function တစ်ခုရဲ့ output ကို မှတ်ထားပေးတဲ့ React hook တစ်ခုဖြစ်ပါတယ်။ useMemo က argument နှစ်ခုလက်ခံပါတယ်။ ပထမ argument မှာ function၊ ဒုတိယ argument မှာတော့ dependency တွေ ဖြစ်ပါတယ်။ useMemo က function တစ်ခုကိုခေါ်ပြီးတော့ အဲဒီ function ရဲ့ return value ကို ပြန်ပြီးတော့ return ပြန်ပေးပါတယ်။
useMemo ကို ခေါ်တဲ့အချိန်တိုင်း သူက dependency တွေ တန်ဖိုးပြောင်းမပြောင်း အရင်စစ်ဆေးပေးပါတယ်။ မပြောင်းဘူးဆိုရင် သ ူ cache လုပ်ထားတဲ့ return value ကိုပဲ ပြန်ပြီးတော့ return ပြန်ပေးပါတယ်။ Function ကို ပြန်မခေါ်တော့ဘူး။ တကယ်လို့ dependency တွေ တန်ဖိုးပြောင်းသွားမယ်ဆိုရင် အဲဒီ function ကို သူကခေါ်ပေးပါတယ်။
အရင်ဆုံး ကိုယ့်ရဲ့ code ဟာ useMemo ကို သုံးစရာမလိုအောင်ရေးပါ။ တစ်နည်းပြောရရင် useMemo ကို direct function များဖြင့်အစားထိုးနိုင်ပြီးတော့ performance ကလွဲ၍ application ကို မပြောင်းလဲပါနဲ့။ ဒီလိုလုပ်ဖို့အလွယ်ဆုံးနည်းလမ်းကတော့ useMemo မပါဘဲ အရင်ရေးပါ။ လိုအပ်လာမှပဲ useMemo ကို ပြန်ထည့်ပါ။
ပိုပြီးတော့ နားလည်အောင် အောက်က example ကို ကြည့်ပါ။ အရင်ဆုံး useMemo မပါဘဲ ရေးကြည့်ရအောင်။
import React, {useState} from ‘react’; function App() { const [length, set_length] = useState(3); const [name, set_name] = useState(‘John Doe’); return ( <> <input value={name} onChange={e => set_name(e.target.value)} /> <NameDisplay name={name}/> <hr /> <input value={length} onChange={e => set_length(Number(e.target.value))} /> <FibDisplay length={length} /> </> ); } function FibDisplay({length}) { console.log(‘Calculating numbers & rerendering…’); const numbers = [1, 1]; for (let i = 2; i < length; i++) { numbers[i] = numbers[i — 1] + numbers[i — 2]; } return <p>{length} numbers of the fibonacci sequence: {numbers.join(‘, ‘)}</p>; } function NameDisplay({name}) { console.log(‘Rerendering name…’); return <p>Your name is {name}</p>; } export default App;
;
ဒီသေးငယ်တဲ့ application လေးက သင့်နာမည်နှင့် နံပါတ်တစ်ခုကို တောင်းပါလိမ့်မယ်။ ထို့နောက် Fibonacci sequence က နံပါတ်များကိုပြပါလိမ့်မည်။ name နှင့် length ကို ပြောင်းတဲ့အချိန်မှာ NameDisplay Component နှင့် FibDisplay Component က (ကြီးမားတဲ့ တွက်ချက်မှုနှင့်အတူ) re-render လုပ်ပါတယ်။ ဒီအရာက app ကို လေးစေပါတယ်။ ဒါဆိုရင် ဘယ်လိုပြုပြင်ရမလဲ။
import React, {useState, useMemo} from ‘react’; function App() { const [length, set_length] = useState(3); const [name, set_name] = useState(‘John Doe’); return ( <> <input value={name} onChange={e => set_name(e.target.value)} /> <NameDisplay name={name}/> <hr /> <input value={length} onChange={e => set_length(Number(e.target.value))} /> <FibDisplay length={length} /> </> ); } function FibDisplay({length}) { const numbers = useMemo(() => { console.log(‘Calculating numbers…’); const result = [1, 1]; for (let i = 2; i < length; i++) { result[i] = result[i — 1] + result[i — 2]; } return result; }, [length]); return <p>{length} numbers of the fibonacci sequence: {numbers.join(‘, ‘)}</p>; } const NameDisplay = React.memo(function ({name}) { console.log(‘Rerendering name…’); return <p>Your name is {name}</p>; }); export default App;
;
ပထမဦးစွာ, FibDisplay အတွက် useMemo ၏အသုံးပြုပုံကိုသတိပြုပါ။ length ပြောင်းလဲသွားမှပဲ run မယ့် function ထဲမှာ ကြီးမားတဲ့ တွက်ချက်မှု (fibonacci တွက်ချက်မှု) ကို ထည့်ထားလိုက်ပါတယ်။ Component က re-render လုပ်ပေမဲ့လည်း ကြီးမားတဲ့ တွက်ချက်မှုကို လိုအပ်မှပဲ run မှာပါ။
ဒုတိယအချက်မှာ NameDisplay Component တစ်ခုလုံးကို React.memo နှင့် wrap လုပ်ထားပါတယ်။
React.memo ကတော့ component တစ်ခုလုံးကို မှတ်ထားပေးပါတယ်။ ၎င်းရဲ့ prop တွေ ပြောင်းမှပဲ component ကို re-render လုပ်ပါတယ်။
Performance အကောင်းဆုံး လုပ်ထားသော်လည်း သူ့ရဲ့ သက်ရောက်မှုများနှင့် ဆိုးကျိုးများကို အမြဲထည့်သွင်းစဉ်းစားသင့်ပါတယ်။ React.useMemo မှာ ပြဿနာ အနည်းငယ်ရှိပါတယ်။
- Hook တွေကိုယ်တိုင်က ရှုပ်ထွေးသော logic အသစ်ကိုမိတ်ဆက်ပေးပ ြီး သူဖြေရှင်းနိုင်တာထက် performance ကျအောင် လုပ်နေနိုင်ပါတယ်။ ကြီးမားသောတွက်ချက်မှုတစ်ခုမဟုတ်လျှင် useMemo ကိုအသုံးမပြုပါသင့်ပါ။
React.memo ကို pure component တွေမှာပဲ အသုံးပြုသင့်ပါတယ်။ Redux/Context နှင့် သူတို့ရဲ့ hook တွေသုံးတဲ့အချိန်မှာလည်း React.memo နဲ့ ပြဿနာအနည်းငယ်ရှိပါတယ်။ Hook တွေကို မသုံးခင် Redux selector တွေက store values တွေကို prop တွေကနေ pass လုပ်ပါတယ်။ အဲဒီ pass လုပ်တဲ့ prop တွေကို React.memo က ဖမ်းယူ (capture) ထားပါတယ်။ ဒါပေမဲ့ useSelectors/useContext တွေကို သုံးတဲ့အချိန်မှာ React.memo က prop တွေပြောင်းပေမဲ့လည်း component ကို re-render လုပ်မှာ မဟုတ်ပါဘူး။