فرق بین Component و PureComponent در React

چون با کمی تاخیر دارم این مبحث رو توضیح میدم , یکسری مثال همراه با مقاله آوردم که هم متفاوت باشه و هم مخاطبین با نمونه کدهای عملی موضوع رو بهتر متوجه بشن و بنظرم این سبکی خیلی بهتره !!!

قبلا که می خواستیم یک پروژه react رو شروع کنیم می آمدیم react رو import و کلاسمون رو extends به Component می کردیم و ادامه ماجرا ... البته هنوزم اینکار شدنی و برای بعضی موارد ایده آل هستش ولی از نسخه 16 به بعد یک قابلیت جدیدی به اسم PureComponent به react اضافه شد که تا حد زیادی روی Performance کنترل خوبی داره و با کمک این امکان میشه اپلیکیشن رو بهینه سازی کرد.

کلاس های Component

وقتی شما یک کلاس رو extends به component می کردید با هر بار تغییر روی state و props یکبار عملیات render توسط متد مربوطه انجام می شد و فرض کنید توی یک فضای تعاملی با action های خیلی زیاد هر سری بخواد این قضیه تکرار بشه خیلی خوشایند به نظر نمیرسه. برای مثال به کد زیر توجه کنید :

https://gist.github.com/buglessir/f8bad7970d759edf33fecb77768b2191

توی این مثال ما یک کامپوننت داریم که قراره یک تگ h1 و دکمه رو نمایش بده. وقتی روی دکمه کلیک میشه مقدار state.name داخل h1 قرار میگیره و اسم رو می بینیم. البته داخل متد render رو توجه کنید , من یک console.log گذاشتم که ببینیم چقدر توی یک اجرای ساده مرحله render در کامپوننت انجام میگیره.

خوب کد بالا رو خودتون هم اجرا کنید , یکبار به خاطر لود شدن کامپوننت Render در کنسول چاپ میشه و یکبار هم وقتی روی دکمه کلیک می کنید. البته یکبار نیست !!! هزار بار روی دکمه بزنید این کلمه Render در کنسول چاپ میشه و این یعنی با هر بار تغییر state و انجام setState داره render اجرا میشه و فرض کنید بجای این کد ساده یک کامپوننت غول با ده ها بچه و زیر مجموعه دارید , چه اتفاقی می افته ؟!؟!

نکته : در نظر داشته باشید در همه حالت که کلیک می کنید مقدار ثابت Mohammad به state پاس داده میشه و render شما برای یک مقدار ثابت و یکسان مدام تکرار میشه و نه متفاوت. یعنی Mohammad به Ali یا مقدار دیگه تبدیل نمیشه.

این یعنی نظارتی در خصوص مقدار state و یکسان بودنش در کلاس های Component وجود نداره و همیشه این روال طی میشه که چندان جالب نیست.

کلاس های PureComponent

تو مثال قبلی متوجه نحوه عملکرد component ها شدیم و حالا تو این مثال قراره از روشی دیگه یعنی همون PureComponent ها استفاد کنیم ببینیم خروجی به چه شکل میشه :

https://gist.github.com/buglessir/69a950d4c51147ce0a9f9a5acd5f44b0

بله , اگر این کد رو اجرا کنید یکبار با لود شدن کامپوننت Render در کنسول چاپ میشه و یکبار هم با کلیک بر روی دکمه و دیگه هزار بار هم روی دکمه کلیک کنید اتفاقی نمی افته و این یعنی از render شدن مجدد کامپوننت در شرایطی که نیاز نیست جلوگیری می کنه. یعنی اینجا یک متد shouldComponentUpdate رو به صورت خودکار و آماده دارید که به قولی یک Shallow Comparison یا همون مقایسه سطحی رو روی state و props انجام میده و اگر متوجه تغییر جدید بشه یک return true داره و مجوز render شدن کامپوننت صادر میشه و از render شدن الکی زمانیکه state و props با مقدار قبلی یکسان هستن جلوگیری می کنه !!!

نکته : در نظر داشته باشید state ما اینجا همواره یکسان و Mohammad هستش و هنوز تغییری نداشته که متوجه یکسان نبودن بشه.

حالا در صورتیکه state یا props تغییر داشته باشه چی میشه !؟ برای درک این قضیه من اومدم اینجا روی خط 15 یک عدد رندم به آخر state جدید اضافه کردم که همون متد shouldComponentUpdate متوجه تغییر بشه و کامپوننت رو render کنه و دیگه مقدار Mohammad ثابت بر نگرده.

به کد زیر توجه کنید :

https://gist.github.com/buglessir/41be29e13c26b7af0aa59e7338507730

حالا کد رو اجرا کنید , بله درسته ! چون یک عدد رندم به ته مقدار جدید state اضافه میشه PureComponent تغییر رو متوجه و render دوباره انجام میشه و با هر بار کلیک روی دکمه Render در کنسول چاپ میشه.

حالا چه زمانی Component و PureComponent رو استفاده کنیم ؟

البته این امکان جدید الان وجود داره , ولی قرار نیست مثل نقل و نبات ازش استفاده کنید و خود react شرایطی رو به شرح زیر در نظر گرفته :

  • زمانیکه data structure شما complex یا همون پیچیده نیست
  • زمانیکه data شما hierarchy یا سلسه مراتب خاصی نداره
  • باید همواره data رو بصورت Immutable به component ارسال کنید
  • زمانیکه تغییرات زیادی روی data انجام میشه متد forceUpdate رو اجرا کنید
  • تمام کامپوننت های زیر مجموعه باید بصورت PureComponent باشند

نتیجه گیری

بنابراین نتیجه می گیریم که اگر می خواید یک مقایسه سطحی روی داده های ساده و غیر پیچیده که به ورودی کامپوننت شما حالا از راه state یا props ارسال میشن انجام بدید بایستی از PureComponent ها استفاده کنید , البته با در نظر گرفتن یکسری شرایط که در چند خط بالاتر براتون لیست کردم.

در نظر داشته باشید برای function component ها هم همچین مسئله ای وجود داره و در مقاله بعدی سعی دارم در خصوص این امکان هم توضیحاتی رو بنویسم.

امیدوارم مورد توجهتون قرار گرفته باشه

موفق باشید