React دائماً کامپوننتها را re-render میکند. بنابراین اگر از اتفاقاتی که در پسزمینه میافتد با خبر باشیم میتوانیم برنامه React خود را طوری تنظیم کنیم که سرعت بسیار بالایی داشته باشد. در این مقاله قصد داریم تا درمورد تکنیکهای پیشرفتهای که برای بهینه سازی عملکرد در React در جهت افزایش سرعت برنامههای React وجود دارد، صحبت کنیم.
React.memo
یک کامپوننت higher-order است و عملکرد کامپوننتهای فانکشنال را در React بهینه میکند. همچنین نتیجه رندر یک کامپوننت را ذخیره میکند و تنها در صورتی که propهای آن تغییر کنند، کامپوننت را دوباره رندر میکند.
در ادامه مثالی از نحوه استفاده از React.memo
را بررسی میکنیم:
export function MyComponent({ prop1, prop2 }) { return ( <div> <div>{prop1}</div> <div>{prop2}</div> </div> ) } export const MemoizedComponent = React.memo(MyComponent)
در این مثال، MyComponent
یک کامپوننت فانکشنال است که دو prop را میپذیرد: prop1 و prop2. با قرار دادن آن بین پرانتزهای کامپوننتReact.memo
، React فقط در صورتی که هر یک از propهای آن تغییر کند، کامپوننت را دوباره رندر میکند.
استفاده از React.memo
برای موارد زیر مفید است:
باید این موضوع را به خاطر داشته باشیم که React.memo
فقط یک مقایسه سطحی از propهای خود را انجام میدهد. اگر کامپوننت ما آبجکت و یا آرایههای پیچیده را به عنوان props دریافت میکند، ممکن است نیاز به ایجاد یک تابع مقایسه سفارشی داشته باشیم.
ویژگی Lazy loading در React این امکان را به ما میدهد که کامپوننتها را بر اساس درخواست لود کنیم. این ویژگی بسیار کارآمدتر از لود همه چیز به طور همزمان و در هنگام شروع برنامه است. از تابع React.lazy()
برای ایجاد یک کامپوننت جدید استفاده میکنیم که میتواند به صورت lazily لود شود. این تابع یک import پویا میگیرد، که یک ویژگی جاوااسکریپت است و لود ماژولها را در صورت درخواست امکانپذیر میکند.
در ادامه مثالی از نحوه استفاده از Lazy loading را باهم بررسی میکنیم:
const MyLazyComponent = React.lazy(() => import('./MyComponent'))
MyComponent
کامپوننتی است که میخواهیم آن را به صورت Lazy لود کنیم. در صورت نیاز، تابع import()
ماژول حاوی MyComponent
را لود میکند. برای استفاده از MyLazyComponent
، آن را در یک کامپوننت لود شده قرار میدهیم:
function MyApp() { return ( <div> <h1>Welcome to my app!</h1> <React.Suspense fallback={<h1>Loading...</h1>}> <MyLazyComponent/> </React.Suspense> </h1> ); }
همینطور در این مثال، MyApp
یک کامپوننت لود شده است. هنگامی که MyApp
رندر میشود، React.Suspense
برای نمایش یک رابط کاربری بازگشتی، مانند نشانگر لود مورد استفاده قرار میگیرد. هنگامی که MyLazyComponent
لود شد، جایگزین رابط کاربری بازگشتی میشود.
Lazy loading برای برنامههای بزرگ با کامپوننتهای متعدد مفید است و میتواند به کاهش زمان لود اولیه و بهبود عملکرد کلی کمک کند.
هوک useCallback
در React توابع را به خاطر میسپارد (ذخیره میکند) تا عملکرد کامپوننتهای فانکشنال را بهینه کند. هنگامی که یک تابع داخل useCallback
قرار میگیرد، تنها زمانی re-render میشود که dependencyهای آن تغییر پیدا کند.
در ادامه مثالی از نحوه استفاده از useCallback
را بررسی میکنیم:
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
تعداد دفعاتی که روی دکمه کلیک شده است را در خود نگه میدارد. همچنین یک تابع handleClick
داریم که با کلیک روی دکمه، متغیر state شمارش را افزایش میدهد.
ما از useCallback
برای به خاطر سپردن تابع handleClick
استفاده کرده و [count]
را به عنوان آرایه dependency آن مشخص میکنیم. این بدان معنی است که این تابع تنها در صورت تغییر تعداد دوباره ایجاد میشود، نه در هر بار re-render کامپوننت.
استفاده از useCallback
به ویژه در سناریوهایی میتواند مفید باشد که در آن یک تابع به عنوان یک prop به کامپوننت child منتقل میشود. با به خاطر سپردن تابع با استفاده از useCallback
، میتوانیم از re-render شدن غیرضروری کامپوننتهای child که به آن تابع وابسته هستند جلوگیری کنیم.
باید به این نکته توجه داشته باشیم که از هوک useCallback
فقط در مواقع ضروری استفاده کنیم، زیرا میتواند پیچیدگیهایی را به کد ما اضافه کند. بهتر است از این هوک هنگام انتقال توابع به عنوان prop به کامپوننتهای child و یا برای توابعی که به منابع زیادی نیاز دارند، استفاده کنیم.
توسعهدهندگان برای بهینه سازی عملکرد در React، از پراپ key برای شناسایی هر آیتم در لیستی از کامپوننتها استفاده میکنند. هنگامی که لیستی از کامپوننتها render میشود، استفاده از یک key میتواند با کمک به React در شناسایی موارد تغییر یافته، عملکرد را بهبود ببخشد.
در ادامه سه نکته برای استفاده موثر از پراپ key را داریم:
در ادامه مثالی از نحوه استفاده از key هنگام رندر کردن لیستی از کامپوننتها را باهم بررسی میکنیم:
function MyList(props) { const items = props.items.map(item => ( <MyListItem key={item.id} item={item} /> )); return <ul>{items}</ul>; }
MyList
کامپوننتی است که فهرستی از کامپوننتهای MyListItem
را رندر میکند. پراپ key روی item.id
تنظیم شده است که یک شناسه منحصربهفرد برای هر آیتم در لیست است.
استفاده از key میتواند با به حداقل رساندن رندر مجدد غیرضروری کامپوننتها در یک لیست، به بهبود عملکرد در React کمک کند. React با استفاده از یک کلید منحصربهفرد و پایدار برای هر آیتم، میتواند به راحتی تشخیص دهد که کدام یک از آیتمها تغییر کردهاند و باید به روز رسانی شوند.
تکنیکهای زیادی برای بهینه سازی عملکرد در React وجود دارد اما ما در این مقاله چهار مورد از آنها را مورد بررسی قرار دادیم که عبارتند از:
دیدگاهها: