-اول باید بدونیم useMemo چیه ؟ یه React hook هست که به عنوان آرگمان اول یه function و به عنوان آرگمان دوم یه آرایه از dependency ها میگیره . در طول رندر اولیه، useMemo فانکشن رو فراخوانی میکنه و نتیجه حاصل از اجرای function رو برمیگردونه و توی حافظه ذخیره میکنه . اگر در طول render های بعدی، dependency ها تغییر نکنه، useMemo فانکشن رو فراخوانی نمی کنه و فقط مقدار ذخیره شده رو برمی گردونه.
بریم سراغ یه مثال ، وارد این لینک بشید
توی App.js یه input داریم برای نوشتن و یه دکمه که هر وقت روش کلیک کنی counter یکی زیاد میشه و یه ChildComponent داریم که count , incrementCount رو به عنوان props بهش پاس میدیم.
وقتی داخل input چیزی مینویسیم یا وقتی رو دکمه Increment کلیک میکنیم متوجه تاخیر زیادی میشیم
-دلیلش چیه ؟ توی این مثال ما یه فانکشن سنگییییین داریم :)) به اسم expensiveFunction که ۲ تا کار انجام میده یه for loop توش نوشتیم که یه delay ایجاد کنه و اینکه سه برابر count رو برمیگردونه
و هر وقت app ما rerender میشه expensiveFunction رو invoke میکنه و همین اتفاق app رو کند میکنه.
در واقع expensiveFunction فقط باید زمانی که رو دکمه Increment کلیک میکنیم call بشه نه زمانی که تو input چیزی مینویسیم
راه حل : ما باید مقدار بازگشتی expensiveFunction رو memoize کنیم (با استفاده از useMemo عزیزم)
فقط کافیه توی خط ۱۷ ام myCount رو اینطوری تعریف کنی
const myCount = React.useMemo(() => {return expensiveFunction(count);}, [count]);
از لحاظ سیتکسی شبیه useMemo هست فقط وقتی که dependency ها تغییر می کنه، function رو برمی گردونه و از rerender شدن غیرضروری جلوگیری میکنه .
وارد این لینک بشید
تقریبا مثل مثال بالا توی App.js یه input داریم برای نوشتن و یه دکمه که هر وقت روش کلیک کنی counter یکی زیاد میشه و یه ChildComponent داریم که count , incrementCount رو به عنوان props بهش پاس میدیم.
-خب حالا مشکل چیه؟ مشکل اینه که وقتی شما توی input چیزی تایپ میکنی ChildComponent داره بیخودی rerender میشه (یعنی هر وقت App ما rerender بشه ChildComponent هم rerender میشه) در صورتی که فقط اگر روی دکمه Increment کلیک شد باید rerender بشه
برای جلوگیری از این اتفاق باید از useCallback استفاده کنیم
فقط کافیه کد خط پایین رو جایگزین خط ۹ ام codesandbox کنی
const incrementCount = React.useCallback(() => setCount(count + 1), [count]);
-خلاصه :useMemo وقتی که dependency ها تغییر میکنن تابع رو فراخوانی میکنه و یه مقدار ذخیره شده رو برمی گردونه و useCallback وقتی که dependency ها تغییر می کنن تابع ذخیره شده رو برمی گردونه .