چگونه تفاوت بین توابع و کامپوننت های کلاس را در React درک کنیم
ﺯﻣﺎﻥ ﻣﻄﺎﻟﻌﻪ: 6 دقیقه

چگونه تفاوت بین توابع و کامپوننت های کلاس را در React درک کنیم

استفاده از کامپوننت ها در react با درک بهتر از چگونگی تأثیر آنها بر عملکرد برنامه همیشه موضوعی گیج کننده بوده است و در نهایت توسعه دهندگان به یک مجموعه کد بزرگ برخورد می‌کنند که مدیریت آن در طول زمان دشوارتر می‌شود. بنابراین پاسخ اصلی که خواهید شنید این است که کامپوننت های کلاس دسترسی به ویژگی‌های بیشتری مانند state را فراهم می‌کنند، اما با Hookها دیگر معتبر نیستند.

حتما در مورد عملکرد بهتر یکی از آنها شنیده‌اید، اما عملکرد نه به انتخاب کلاس یا تابع بلکه به آنچه کد انجام می‌دهد بستگی دارد. این عملکرد تقریبا یکسان است و می‌تواند با استفاده از تکنیک‌های مختلف بهینه سازی تفاوت‌هایی ایجاد کند.

کامپوننت های تابع

یک کامپوننت را در نظر بگیرید. بیایید با استفاده از یک کامپوننت ساده که یک درخواست شبکه را با setTimeout شبیه سازی می‌کند و یک هشدار تأیید را نشان می‌دهد، مثالی بزنیم. اگرprops.user  برابر "Mohit" باشد، پس از 3 ثانیه "Followed Mohit" را نشان می‌دهد.

در مثال بالا می‌توانید از پیکان‌ها یا اعلان توابع نیز استفاده کنید که هر دو یک کار را انجام می‌دهند.

پیاده سازی مثال فوق در کلاس:

اغلب اوقات مردم به اشتباه به هر دو روش به طور یکسان نگاه می‌کنند، اما بین نتایجی که به دست می‌آید، تفاوت وجود دارد. برای مشاهده تفاوت می‌توانید لینک کد ایجاد شده را برای درک بهتر باز کنید.

صفحه کد ارائه شده در بالا را باز کرده و کد را اجرا کنید، اکنون این مراحل را امتحان کنید تا تفاوت را ببینید.

روی دکمه follow کلیک کنید. (تابع یا کلاس، می‌توانید هر یک از آنها را انتخاب کنید)

پروفایل انتخاب شده را قبل از گذشت 3 ثانیه تغییر دهید. اکنون هشدار نوشتاری را بخوانید.

وقتی روی دکمه follow کلیک می‌کنیم (با استفاده از یک کامپوننت تابع) توسط یک اعلان کوچک در بالا مطلع شده و سپس به پروفایل دیگری می‌رویم، که نام کاربری قبلی را به جای آنچه در 3 ثانیه بعد انتخاب کردیم نشان می‌دهد. اما وقتی دکمه follow را می‌فشاریم (با استفاده از یک کامپوننت کلاس) هر بار نام کاربر تازه انتخاب شده را نشان می‌دهد. اگر خودتان کد را اجرا کنید و این مراحل را انجام دهید، بهتر آن را درک خواهید کرد.

در این مثال اگر دکمه follow در پروفایل "Mohit" را فشار دهید و سپس کاربر انتخاب شده را تغییر دهید، در صورت استفاده از کامپوننت تابع هنوز می‌خواهید Mohit را در دیالوگ باکس هشدار مشاهده کنید و در مورد کامپوننت کلاس، نام پروفایل سوئیچ شده را در دیالوگ باکس هشدار مشاهده خواهید کرد.

همانطور که مشاهده می‌کنید، رفتار اول کاملا همان چیزی است که ما ادعا می‌کنیم برای ما صحیح است، زیرا کامپوننت نباید در مورد کسی که دنبال کردم اشتباه کند.

بنابراین دلیل این رفتار اشتباه چیست؟

برای درک این موضوع بیایید نگاهی دقیق به متد showMessage در کلاس خود بیندازیم.

متد class از this.prop.user می‌خواند و propها در react تغییرناپذیر هستند، بنابراین هرگز نمی‌توانند تغییر کنند. اما این همیشه قابل تغییر بوده است و در واقع هدف کل یک کلاس است، زیرا react آن را در render و چرخه حیات تغییر می‌دهد تا بتوانیم نسخه جدید را در render به روز کنیم. اگر کامپوننت ما در حین پردازش مجددا رندر شود، this.props تغییر می‌کند و متد showMessage کاربر را از propهای جدید می‌خواند.

این موضوع ارتباط جالبی را در ماهیت رابط‌های کاربری نشان می‌دهد و اگر بگوییم رابط کاربری تابعی از وضعیت برنامه فعلی است، کنترل کننده‌های رویداد بخشی از نتیجه render می‌شوند. اما برنامه ریزی یک وقفه زمانی که this.props را می‌خواند، ارتباط را از بین می‌برد.

بنابراین بگذارید بگوییم چیزی به عنوان کامپوننت تابع وجود ندارد، پس راه حل این مشکل چه خواهد بود؟

اگر بخواهیم ارتباط بین render و propهای صحیح و فراخوانی showMesage که آنها را می‌خواند اصلاح کنیم، یکی از راه‌هایی که می‌توانیم به این امکان دست یابیم آن است که this.props را در اوایل رویداد بخوانیم و سپس آنها را از طریق کنترل کننده زمان اتمام عبور دهیم. هنوز هم این رویکرد باعث می‌شود که کد در نهایت مستعد خطا باشد و ما نمی‌توانیم از بیش از یک prop استفاده کنیم. همچنین نمی‌توانیم به state دسترسی پیدا کنیم و سرانجام دوباره با همان مشکلات روبه رو خواهیم شد.

حتی اگر کد هشدار را در داخل handleClick قرار دهیم، به مشکلات بزرگتر پاسخ نمی‌دهد. هدف این است که کد ما به گونه‌ای ساخته شود که امکان تقسیم آن به روش‌های بیشتر و همچنین امکان خواندن propها و state مربوط به render وابسته به آن فراخوانی را فراهم کند.

اگر متدها را در constructor بایند کنیم چه می‌شود؟

بخاطر بسپارید که مشکل در دیر خواندن this.props است، نه سینتکسی که ما استفاده می‌کنیم. بنابراین این مشکل را حل نمی‌کند. اگر به closureهای جاوااسکریپت اعتماد کنیم، مشکل قابل حل خواهد بود.

با این حال از closureها اجتناب می‌شود؛ زیرا فکر کردن در مورد چیزی که می‌تواند اضافه کاری را بیشتر کند، دشوار است. بنابراین اگر از closureها بر روی propها یا state در render استفاده کنیم، به راحتی می‌توانیم روی آنها حساب کنیم.

کامپوننت های تابع مقادیر رندرشده را ثبت می‌کنند

اگر ما توابع را داخل render تعریف کنیم، داشتن کلاس چه فایده‌ای دارد؟

هنگامی که کامپوننت والد ProfilePage را با برنامه‌های مختلف رندر می‌کند، react تابع ProfilePage را دوباره فراخوانی کرده و کنترل رویدادی که قبلا کلیک کردیم مربوط به رندر قبلی است که دارای ارزش کاربری خاص خود است و توسط showMessage خوانده می‌شود. به همین دلیل است که در مثال فوق هنگامی که پس از تغییر کاربر انتخاب شده بر روی follow Mohit کلیک می‌کنیم، همچنان "Followed Mohit" نشان داده می‌شود.

منبع

چه امتیازی برای این مقاله میدهید؟

خیلی بد
بد
متوسط
خوب
عالی
در انتظار ثبت رای

/@erfanheshmati
عرفان حشمتی
Full-Stack Web Developer

کارشناس معماری سیستم های کامپیوتری، طراح و توسعه دهنده وب سایت، تولیدکننده محتوا

دیدگاه و پرسش

برای ارسال دیدگاه لازم است وارد شده یا ثبت‌نام کنید ورود یا ثبت‌نام

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

در حال دریافت نظرات از سرور، لطفا منتظر بمانید