ابزار ()memo و بررسی تخصصی React Memo !

·

5 min read

ابزار memo ری اکت یکی از مهمترین قابلیت هایی هست که تو بحث بهینه سازی میتونیم ازش استفاده کنیم.

در حقیقت memo به ما اجازه میده از re-Render اضافی کامپوننت تا زمانیکه Props اون تغییری نکرده، جلوگیری کنیم.

چه حسی از این بهتر که وقتی کاربر آدرس سایت شمارو میزنه کمتر از 100ms بتونه سایت رو ببینه ؟! و چه حسی بدتر از اینکه زمان Load سایت به 300ms برسه ؟

قطعا نمیشه اهمیت بهینه سازی ( Performance ) تو وبسایت رو نادیده گرفت یا انکار کرد .

اگه شماهم مثل من یه React Developer هستی باید با ابزار ()memo تو React خیلی خوب آشنا باشی و بدونی چطور باید ازش کمک بگیری تا بتونی Performance اپیکیشن خودت رو به حداکثر میزان ممکن برسونی 🙂

چند روز پیش راجب Lazy Load تصاویر ری اکت صحبت کردیم که اونم در رابطه با Performance وبسایت های ری اکتی بود و امروز میخوایم بصورت تخصصی راجب ویژگی ()memo صحبت کنیم .

برای اینکه بدونیم ویژگی قابلیت memo چیه و چطور کار میکنه ، لازمه بدونیم دام مجازی ری اکت چطور کار میکنه . (مطالعه کنید : دام مجازی ری اکت )

زمانی که حالت یکی از Element های DOM تغییر میکنه ، ری اکت اون تغییر رو render میکنه و با render قبل از تغییر مقایسه میکنه .

اگه تو این مقایسه اِلِمانی تغییر کرده باشه ، Element تغییر پیدا کرده داخل DOM بروزرسانی میشه .

این اتفاق با سرعت خیلی زیادی رخ میده ، اما به کمک ابزار ()React.memo میتونیم این سرعت رو بیشتر هم بکنیم .

اگر ما یک کامپوننت رو داخل ()memo بزاریم ، ری اکت اون کامپوننت رو render میکنه و نتیجه ی render رو به حافظش میسپاره !

حالا اگه اون کامپوننت نیاز به re-Render داشته باشه ، ری اکت اول props های اون کامپوننت رو با props های اون کامپوننتی که تو حافظش ذخیره کرده چک میکنه.

اگه props ها یکسان باشن ، ری اکت همون کامپوننتی که تو حافظش ذخیره کرده بوده رو نشون میده و دیگه re-Render صورت نمیگیره !

اجازه بدید memo رو تو واقعیت ببینیم 🙂

export function Music({ title, description }) {
  return (
    <div>
      <div>Music title: {title}</div>
      <div>Desc: {description}</div>
    </div>
  );
}

export const MemoizedMusic = React.memo(Music);

تو تیکه کد بالا ، ما کامپوننت Music رو داخل ()React.memo قرار دادیم .

اگه به خط 10 دقت کنید میبینید که React.memo(music) یک مقدار جدید Return کرده به اسم MemoizedMusic .

در واقع خروجی کامپوننت MemoizedMusic با خود کامپوننت Music کاملا یکسانه ! با این تفاوت که کامپوننت MemoizedMusic فقط یکبار render میشه و تا زمانی که props هاش تغییر نکنه ، re-Render نمیشه !

اما کامپوننت Music هر بار render میشه ( فارغ از اینکه props های اون تغییر میکنه یا نه )

// اولین رندر => این کامپوننت به حافظه ری اکت میره و ذخیره میشه
<MemoizedMusic
  title="تنها در خانه"
  description="فیلم خوبیه"
/>

// دومین رندر => چون پراپس های این کامپوننت تغییر نکرده ، مجدد رندر نمیشه و از حافظه فراخوانی میشه
<MemoizedMusic
  title="تنها در خانه"
  description="فیلم خوبیه"
/>

تو تیکه کد بالا ما 2 بار کامپوننت MemoizedMusic رو فراخوانی کردیم ولی فقط 1 بار render میشه .

ری اکت دفعه اول که به این کامپوننت برمیخوره ، اون رو render میکنه و تو حافظه خودش نگه میداره.

دفعه بعدی که همون کامپوننت رو فراخوانی کردیم ، چون props هاش تغییری نکردن ، پس مجدد رندر نمیکنه و فقط از حافظش همون رو فراخوانی میکنه .

به همین سادگی شما میتونید کلی نقش مثبت تو Performance اپیکیشن خودتون داشته باشید 🙂

بررسی دستی یکسان بودن Props ها در memo

علاوه بر اینکه ری اکت خودش میتونه اینکار رو بکنه ، شما میتونید خودتون یک Fumction اختصاصی بنویسید و اون رو به memo پاس بدید:

React.memo(Component, [CheckPropsEqual(prevProps, nextProps)]);

تو تیکه کد بالا ، خودمون یک کامپوننت CheckPropsEqual نوشتیم که دو Props به عنوان ورودی میگیره و چک میکنه که آیا Props ها یکسان هستند یا خیر .

نتیجه باید boolean ( true/false ) باشه . نتیجه True به معنی مساوی بودن Props ها هست .

چه زمانی از ()React.memo استفاده کنیم ؟

1 – جاهایی که فکر میکنید کامپوننت با Props های یکسان render میشه !

یکی از بهترین جاهایی که میشه از react.memo استفاده کرد ، کامپوننت هایی هستن که اغلب با Props های یکسان render میشن !

بیاید یک سناریویی رو در نظر بگیریم که یک سایت مشاهده موزیک داریم که بصورت لحظه ای ، میزان نمایش دانلود موزیک رو به کاربر نشون میدیم . ( یعنی هر چند ثانیه یکبار به back-end درخواست میدیم و اطلاعات جدید رو میگیریم )

function MusicViewsRealtime({ title, releaseDate, views }) {
  return (
    <div>
      <Music title={title} releaseDate={releaseDate} />
      Music Download: {views}
    </div>
  );
}

اتفاقی که میوفته :

// بار اول
<MusicViewsRealtime
  views={0}
  title="Forrest Gump"
  releaseDate="June 23, 1994"
/>

//بعد چند ثانیه ، بازدید ده
<MusicViewsRealtime
  views={10}
  title="Forrest Gump"
  releaseDate="June 23, 1994"
/>

// بعد چند ثانیه ، بازدید بیست و پنج
<MusicViewsRealtime
  views={25}
  title="Forrest Gump"
  releaseDate="June 23, 1994"
/>

// ادامه .. .

اتفاقی که میوفته این هست که مقدار views هر چند ثانیه یکبار داره آپدیت میشه و کامپوننت MusicViewsRealtime هر بار re-Render میشه . که باعث میشه کامپوننت Music هم re-Render بشه ( درصورتی که کامپوننت Music هیچ تغییری نداشته ! )

در حقیقت props های کامپوننت Music هیچ تغییری نکردن ، ولی هر دفعه داره re-Render براش رخ میده .

اینجا همون جاییه که باید از React.memo استفاده کنیم :

function MusicViewsRealtime({ title, releaseDate, views }) {
  return (
    <div>
      <MemoizedMusic title={title} releaseDate={releaseDate} />
      Music Download: {views}
    </div>
  );
}

با memo کردن کامپوننت Music ، دیگه هر چند ثانیه یکبار re-Render نمیشه چون Props های اون تغییری نمیکنه.

چه زمانی از ()React.memo استفاده نکنیم ؟

برای مطالعه نسخه کامل این مقاله در وبسایت فِرانت اِندی + مثالها و تیکه کد های بیشتر روی لینک زیر کلیک کنید :

memo در ری اکت