ویرگول
ورودثبت نام
fatemeh....
fatemeh....
fatemeh....
fatemeh....
خواندن ۲ دقیقه·۴ ماه پیش

توابع در JSX: رندر، بهینه‌سازی و Memoization

1.تابع ثابت خارج از JSX

"وقتی تابع را خارج از کامپوننت تعریف میکنیم، فقط یک بار در حافظه ایجاد میشود و مرجع آن در طول اجرای برنامه ثابت باقی می ماند."

function handleClick() { console.log("Clicked"); } const Item = React.memo(({ }) => ( <button ={}>Click</button> )); function App() { return <Item ={handleClick} />; }

در کد بالا چه اتفاقی می افتد ؟

  • وقتی کامپوننت App اجرا میشود، تابع handleClick فقط یکبار ساخته شده و در props به Item ارسال میشود.

  • چون مرجع تابع در رندرهای بعدی تغییر نمیکند، React.memo متوجه میشود که props ثابت ماندهاند و Item دوباره رندر نمیشود.

  • مرجع تابع در رندر های مختلف تغییر نمی کند پس هر بار که کد رندر می شود Item دوباره رندر نمی شود.

نکته ی مهم : اگر تابع داخل App تعریف میشد، مثل:

function App() { const handleClick = () => console.log("Clicked"); return <Item ={handleClick} />; }

در این حالت هر بار که App رندر میشود، یک مرجع جدید از handleClick ساخته میشود و Item با React.memo مجبور به رندر دوباره میشود. با استفاده از useCallback می تونیم این مشکل را حل کنیم.

2.Arrow function مستقیم در JSX

"وقتی تابع را مستقیماً بهصورت Arrow function داخل JSX تعریف میکنیم، در هر رندر یک تابع جدید ساخته میشود و مرجع آن تغییر میکند؛ در نتیجه memoization از کار میافتد."

function App() { return <Item ={() => console.log("Clicked")} />; }

در کد بالا چه اتفاقی می افتد ؟

  • در هر بار رندر کامپوننت App، یک تابع جدید در حافظه ساخته میشود..

از اونجایی که memo فقط مقایسه ی سطحی (shallow) انجام میدهد، در رندرهای بعدی متوجه میشود که مرجع تابع تغییر کرده و نتیجه میگیرد که props تغییر کرده اند.

  • در نتیجه، کامپوننت فرزند (مثل Item) دوباره رندر میشود حتی اگر عملکرد تابع اصلی (handleClick) هیچ تغییری نکرده باشد.

  • به همین دلیل این روش باعث شکست memoization و ایجاد رندرهای غیرضروری میشود.

توصیه: تعریف تابع مستقیم در JSX فقط برای کامپوننتهای کوچک یا بدون memo مناسب است؛ در غیر این صورت باعث رندرهای غیرضروری و کاهش کارایی میشود.

3. تابع تعریفشده با useCallback

"با useCallback، تابع فقط زمانی که وابستگیها تغییر کنند بازسازی میشود و مرجع آن ثابت میماند؛ بنابراین memo درست کار میکند و از رندرهای اضافی جلوگیری میشود."

const Item = React.memo(({ }) => { return <button ={}>Click me</button>; }); function App() { const handleClick = useCallback(() => { console.log("Clicked"); }, []); return <Item ={handleClick} />; }

در کد بالا چه اتفاقی می افتد ؟

  • تابع handleClick با استفاده از useCallback ساخته میشود و تا زمانی که وابستگیهای آن (در اینجا هیچ وابستگی ندارد) تغییر نکنند، مرجع آن ثابت میماند.

  • در نتیجه، React.memo تشخیص میدهد که props تغییری نکردهاند و از رندر مجدد Item جلوگیری میکند.

Memoizationreact
۱
۰
fatemeh....
fatemeh....
شاید از این پست‌ها خوشتان بیاید