تکنیک‌های پیشرفته برای بهینه‌ سازی عملکرد در React

React دائماً کامپوننت‌ها را re-render می‌کند. بنابراین اگر از اتفاقاتی که در پس‌زمینه می‌افتد با خبر باشیم می‌توانیم برنامه React خود را طوری تنظیم کنیم که سرعت بسیار بالایی داشته باشد. در این مقاله قصد داریم تا درمورد تکنیک‌های پیشرفته‌ای که برای بهینه‌ سازی عملکرد در React در جهت افزایش سرعت برنامه‌های React وجود دارد، صحبت کنیم.

استفاده از ()React.Memo

React.memo
React.memo یک کامپوننت‌ higher-order است و عملکرد کامپوننت‌های فانکشنال را در React بهینه می‌کند. همچنین نتیجه رندر یک کامپوننت را ذخیره می‌کند و تنها در صورتی که propهای آن تغییر کنند، کامپوننت را دوباره رندر می‌کند.

در ادامه مثالی از نحوه استفاده از

React.memo
React.memoرا بررسی می‌کنیم:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
export function MyComponent({ prop1, prop2 }) {
return (
<div>
<div>{prop1}</div>
<div>{prop2}</div>
</div>
)
}
export const MemoizedComponent = React.memo(MyComponent)
export function MyComponent({ prop1, prop2 }) { return ( <div> <div>{prop1}</div> <div>{prop2}</div> </div> ) } export const MemoizedComponent = React.memo(MyComponent)
export function MyComponent({ prop1, prop2 }) {
  return (
    <div>
      <div>{prop1}</div>
      <div>{prop2}</div>
    </div>
  )
}
export const MemoizedComponent = React.memo(MyComponent)

در این مثال،

MyComponent
MyComponentیک کامپوننت فانکشنال است که دو prop را می‌پذیرد: prop1 و prop2. با قرار دادن آن بین پرانتزهای کامپوننت
React.memo
React.memo، React فقط در صورتی که هر یک از propهای آن تغییر کند، کامپوننت را دوباره رندر می‌کند.

استفاده از

React.memo
React.memo برای موارد زیر مفید است:

  1. فانکشنال کامپوننت‌هایی که به تعداد بالا رندر می‌شوند
  2. کامپوننت‌هایی که رندر آن‌ها منابع زیادی را نیاز دارد
  3. کامپوننت‌هایی که propهایی را دریافت می‌کنند که مرتباً دچار تغییر نمی‌شوند.

باید این موضوع را به خاطر داشته باشیم که

React.memo
React.memo فقط یک مقایسه سطحی از propهای خود را انجام می‌دهد. اگر کامپوننت ما آبجکت و یا آرایه‌های پیچیده را به عنوان props دریافت می‌کند، ممکن است نیاز به ایجاد یک تابع مقایسه سفارشی داشته باشیم.

Lazy Loading

ویژگی Lazy loading  در React این امکان را به ما می‌دهد که کامپوننت‌ها را بر اساس درخواست لود کنیم. این ویژگی بسیار کارآمدتر از لود همه چیز به طور هم‌زمان و در هنگام شروع برنامه است. از تابع

React.lazy()
React.lazy()برای ایجاد یک کامپوننت جدید استفاده می‌کنیم که می‌تواند به صورت lazily لود شود. این تابع یک import پویا می‌گیرد، که یک ویژگی جاوااسکریپت است و لود ماژول‌ها را در صورت درخواست امکان‌پذیر می‌کند.

در ادامه مثالی از نحوه استفاده از Lazy loading را باهم بررسی می‌کنیم:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const MyLazyComponent = React.lazy(() => import('./MyComponent'))
const MyLazyComponent = React.lazy(() => import('./MyComponent'))
const MyLazyComponent = React.lazy(() => import('./MyComponent'))

MyComponent
MyComponent کامپوننتی است که می‌خواهیم آن را به صورت Lazy لود کنیم. در صورت نیاز، تابع
import()
import()ماژول حاوی
MyComponent
MyComponentرا لود می‌کند. برای استفاده از
MyLazyComponent
MyLazyComponent، آن را در یک کامپوننت لود شده قرار می‌دهیم:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function MyApp() {
return (
<div>
<h1>Welcome to my app!</h1>
<React.Suspense fallback={<h1>Loading...</h1>}>
<MyLazyComponent/>
</React.Suspense>
</h1>
);
}
function MyApp() { return ( <div> <h1>Welcome to my app!</h1> <React.Suspense fallback={<h1>Loading...</h1>}> <MyLazyComponent/> </React.Suspense> </h1> ); }
function MyApp() {
  return (
    <div>
      <h1>Welcome to my app!</h1>
      <React.Suspense fallback={<h1>Loading...</h1>}>
        <MyLazyComponent/>
      </React.Suspense>
    </h1>
  );
}

همینطور در این مثال،

MyApp
MyAppیک کامپوننت لود شده است. هنگامی که
MyApp
MyAppرندر می‌شود،
React.Suspense
React.Suspenseبرای نمایش یک رابط کاربری بازگشتی، مانند نشانگر لود مورد استفاده قرار می‌گیرد. هنگامی که
MyLazyComponent
MyLazyComponentلود شد، جایگزین رابط کاربری بازگشتی می‌شود.

Lazy loading برای برنامه‌های بزرگ با کامپوننت‌های متعدد مفید است و می‌تواند به کاهش زمان لود اولیه و بهبود عملکرد کلی کمک کند.

useCallback

هوک

useCallback
useCallbackدر  React توابع را به خاطر می‌سپارد (ذخیره می‌کند) تا عملکرد کامپوننت‌های فانکشنال را بهینه کند. هنگامی که یک تابع داخل
useCallback
useCallbackقرار می‌گیرد، تنها زمانی re-render می‌شود که dependencyهای آن تغییر پیدا کند.

در ادامه مثالی از نحوه استفاده از

useCallback
useCallbackرا بررسی می‌کنیم:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function MyComponent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(count + 1);
}, [count]);
return (
<div>
<p>Count: {count}</p>
<button> onClick={handleClick}>Increment/button>
</div>
);
}
function MyComponent() { const [count, setCount] = useState(0); const handleClick = useCallback(() => { setCount(count + 1); }, [count]); return ( <div> <p>Count: {count}</p> <button> onClick={handleClick}>Increment/button> </div> ); }
function MyComponent() {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    setCount(count + 1);
  }, [count]);

  return (
    <div>
      <p>Count: {count}</p>
      <button> onClick={handleClick}>Increment/button>
    </div>
  );
}

در این مثال، متغیر

count state
count stateتعداد دفعاتی که روی دکمه کلیک شده است را در خود نگه می‌دارد. همچنین یک تابع
handleClick
handleClickداریم که با کلیک روی دکمه، متغیر state شمارش را افزایش می‌دهد.

ما از

useCallback
useCallbackبرای به خاطر سپردن تابع
handleClick
handleClickاستفاده کرده و
[count]
[count]را به عنوان آرایه dependency آن مشخص می‌کنیم. این بدان معنی است که این تابع تنها در صورت تغییر تعداد دوباره ایجاد می‌شود، نه در هر بار re-render کامپوننت.

استفاده از

useCallback
useCallbackبه ویژه در سناریوهایی می‌تواند مفید باشد که در آن یک تابع به عنوان یک prop به کامپوننت child منتقل می‌شود. با به خاطر سپردن تابع با استفاده از
useCallback
useCallback، می‌توانیم از re-render شدن غیرضروری کامپوننت‌های child که به آن تابع وابسته هستند جلوگیری کنیم.

باید به این نکته توجه داشته باشیم که از هوک

useCallback
useCallbackفقط در مواقع ضروری استفاده کنیم، زیرا می‌تواند پیچیدگی‌هایی را به کد ما اضافه کند. بهتر است از این هوک هنگام انتقال توابع به عنوان prop به کامپوننت‌های child و یا برای توابعی که به منابع زیادی نیاز دارند، استفاده کنیم.

بهینه‌ سازی عملکرد لیست با استفاده از keyها

توسعه‌دهندگان برای بهینه‌ سازی عملکرد در React، از پراپ key برای شناسایی هر آیتم در لیستی از کامپوننت‌ها استفاده می‌کنند. هنگامی که لیستی از کامپوننت‌ها render می‌شود، استفاده از یک key می‌تواند با کمک به React در شناسایی موارد تغییر یافته، عملکرد را بهبود ببخشد.

در ادامه سه نکته برای استفاده موثر از پراپ key را داریم:

  1. بهتر است از یک شناسه منحصربه‌فرد برای پراپ key استفاده کنیم. به جای استفاده از یک ایندکس به عنوان کلید، که می‌تواند در هنگام افزودن یا حذف موارد از لیست، مشکلاتی ایجاد کند باید برای هر موردی که در لیست وجود دارد از یک شناسه منحصربه‌فرد استفاده شود.
  2. از یک شناسه پایدار برای پراپ key استفاده کنیم. در این حالت حتی اگر ترتیب لیست تغییر کند، باید از همان شناسه برای یک مورد خاص استفاده شود. این کار به React کمک می‌کند تا از رندر مجدد غیرضروری جلوگیری کند.
  3. بهتر است پراپ key را به بیرونی‌ترین المنت در دستور بازگشتی یک کامپوننت اعمال کنیم. اعمال کلید بر روی یک المنت داخلی ممکن است باعث بروز یک رفتار غیرمنتظره شود زیرا React از پراپ key برای شناسایی هر کامپوننت استفاده می‌کند.

در ادامه مثالی از نحوه استفاده از key هنگام رندر کردن لیستی از کامپوننت‌ها را باهم بررسی می‌کنیم:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function MyList(props) {
const items = props.items.map(item => (
<MyListItem key={item.id} item={item} />
));
return <ul>{items}</ul>;
}
function MyList(props) { const items = props.items.map(item => ( <MyListItem key={item.id} item={item} /> )); return <ul>{items}</ul>; }
function MyList(props) {
  const items = props.items.map(item => (
     <MyListItem key={item.id} item={item} />
  ));
  return <ul>{items}</ul>;
}

MyList
MyListکامپوننتی است که فهرستی از کامپوننت‌های
MyListItem
MyListItemرا رندر می‌کند. پراپ key روی
item.id
item.idتنظیم شده است که یک شناسه منحصربه‌فرد برای هر آیتم در لیست است.

استفاده از key می‌تواند با به حداقل رساندن رندر مجدد غیرضروری کامپوننت‌ها در یک لیست، به بهبود عملکرد در React کمک کند. React با استفاده از یک کلید منحصربه‌فرد و پایدار برای هر آیتم، می‌تواند به راحتی تشخیص دهد که کدام یک از آیتم‌ها تغییر کرده‍اند و باید به روز رسانی شوند.

جمع‌بندی

تکنیک‌های زیادی برای بهینه‌ سازی عملکرد در React وجود دارد اما ما در این مقاله چهار مورد از آن‌ها را مورد بررسی قرار دادیم که عبارتند از:

  • Memo()
  • Lazy Loading
  • هوک useCallback
  • بهینه سازی عملکرد لیست با استفاده از keyها

دیدگاه‌ها:

افزودن دیدگاه جدید