امیر امیرپور
امیر امیرپور
خواندن ۵ دقیقه·۲ سال پیش

forwardRef

سلام به همه دوستان

در این پست در مورد forwardRef در react صحبت خواهیم کرد.

لینک این پست به زبان انگلیسی در لینکدین


چه مطالبی گفته خواهد شد:

  • مفهوم forwardRef چیست ؟
  • چه زمانی ما به forwardRef نیاز پیدا می کنیم ؟
  • و در انتها چطور از forwardRef استفاده کنیم ؟

شما احتمالا با مفهوم ref در react آشنایی دارید. ما در react می توانیم به المان های DOM از طریق ref دسترسی داشته باشیم.(البته این تنها کاربرد ref در react نیست ولی یکی از رایج ترین موارد مورد استفاده از ref می باشد.)

قطعه کد پایین را مشاهده بفرمایید:‌

پاس دادن ref به عنوان props به المان DOM
پاس دادن ref به عنوان props به المان DOM


در اینجا inputRef برای ما آبجکتی شامل تنها یک کلید به نام current را برمی گرداند.

شما می توانید inputRef را مانند زیر در نظر بگیرید:

const inputRef = { current: some_value };

در اینجا ما می توانیم از طریق inputRef.current به المان input دسترسی داشته باشیم و هر کد جاوااسکریپتی قابل قبول را روش اجرا کنیم.

به عنوان مثال تصور کنید یک button وجود داره و ما می خواهیم با کلیک بر روی این button المان input ما در وضعیت focus قرار بگیره. قطعه کد زیر این کار رو انجام میده:

با کلیک بر روی button المان input در وضعیت focus قرار می گیرد.
با کلیک بر روی button المان input در وضعیت focus قرار می گیرد.


تا اینجا همه چیز به درستی داره کار می کنه اما فرض کنید ما بخواهیم بجای المان input از یک کامپوننت react که خودمون نوشتیم استفاده بکنیم. فرض کنید ما کامپوننتی به نام Input در پروژه خودمون ایجاد کردیم.

لطفا دقت کنید که input با Input تفاوت دارد. input یک المان HTML هست ولی Input یک کامپوننت react هست که ممکنه داخلش شامل چندین المان HTML باشه.

<input /> actual HTML element <Input /> react component

قطعه کد زیر را مشاهده کنید که داخلش ما کامپوننت Input خودمون رو تعریف کردیم:

تعریف کامپوننت Input
تعریف کامپوننت Input


حالا در فایل App.jsx بجای تگ input از کامپوننتی که نوشتیم استفاده می کنیم. قطعه کد زیر رو مشاهده کنید:

استفاده از کامپوننت Input بجای تگ input
استفاده از کامپوننت Input بجای تگ input


اینجا تنها تغییر اینه که ما داریم از کامپوننتی که خودمون نوشتیم بجای تگ input استفاده می کنیم.

بنظرتون کد هنوز هم مثل قبل به درستی کار میکنه ؟

(راهنمایی:‌اگه کد همچنان به درستی کار بکنه این پست بی فایده خواهد بود)

از اونجایی که این پست قرار نیست بی فایده باشه ? (حداقل جوری که من فکر می کنم) جواب سوال قبل اینه که خیر با تغییری که ما دادیم کد الان به مشکل خورده و مثل قبل کار نمی کنه.

در واقع اگر الان داخل کامپوننت Input دستور console.log(props.ref) رو اجرا کنیم مقدار undefined رو خواهیم دید.

چـــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــرا این اتفاق افتاد ؟

خب علت اینه که در react به طور پیش فرض یک کامپوننت اجازه دسترسی به المان های DOM کامپوننت های دیگه نداره. در بیشتر مواقع این اتفاق دقیقا چیزی هست که مورد نیاز ما هست ولی در بعضی مواقع مشابه مثال ما نیاز داریم که یک کامپوننت خاص اجازه دسترسی به بعضی از المان های DOM خودش رو به بقیه کامپوننت ها بده.

برای این کار ما باید خودمون این مورد رو ذکر کنیم.

حالا ما چطور به react بگیم که یکی از کامپوننت های ما مثلا در اینجا Input می خواد اجازه دسترسی به المان input خودش رو به سایر کامپوننت ها بده ؟

(راهنمایی:‌ نگاهی به عنوان این پست بندازید.)

ما در اینجا نیاز به استفاده از forwardRef داریم. در واقع کاری که ما باید بکنیم اینه که inputRef رو به عنوان prop با نام ref به کامپوننت Input پاس بدیم و بعد این ref رو فوروارد کنیم به تگ input که داریم داخل کامپوننت Input رندر می کنیم.

قطعه کد زیر رو مشاهده کنید:

استفاده از forwardRef برای فوروارد کردن inputRef به تگ input
استفاده از forwardRef برای فوروارد کردن inputRef به تگ input


همانطور که مشاهده می کنید تابع forwardRef ابجکت props رو به عنوان آرگومان اول و ref رو به عنوان آرگومان دوم دریافت می کنه. حالا ما می تونیم تعیین کنیم کجا می خواهیم از این ref استفاده کنیم که ما هم این ref رو به تگ input دادیم.

حالا اگر شما دستور console.log(ref) رو در فایل Input.jsx چاپ کنید دیگه مقدار undefined رو نخواهید دید و میتونید هر طور که می خواهید از این ref استفاده کنید.

به کد های زیر نگاهی بندازید که ورژن نهایی هر دو فایل مورد استفاده(App.jsx و Input.jsx) ما در کنار هم هست:

فایل Input.jsx
فایل Input.jsx


فایل App.jsx
فایل App.jsx


همانطور که گفته شد ما با استفاده از forwardRef می تونیم تعیین کنیم که یسری از کامپوننت های ما‌ (در مثال ما Input.jsx) اجازه دسترسی به یسری از المان های خودشون رو به سایر کامپوننت ها بدن.

به نظرتون جالب تر نمی شد اگه ما می تونستیم یسری قانون و قاعده تعریف کنیم و نحوه دسترسی به المان های کامپوننت Input رو محدودتر کنیم ؟ در حال حاظر ما داخل فایل App.jsx می تونیم دستور زیر رو اجرا کنیم:

inputRef.current.focus();

و این دستور باعث میشه که المان input داخل کامپوننت Input تحت تاثیر و در حالت focus قرار بگیره که خیلی هم عالیه.

اما ما همچنین می تونیم یسری کد غیر مرتبط هم از طریق inputRef اجرا کنیم که ممکنه برنامه رو دچار مشکل بکنه. برای مثال قطعه کد های زیر رو در نظر بگیرید:

// these commands are unrelated, but still possible inputRef.current.style.fontSize = &quot10rem&quot inputRef.current.style.display = &quotnone&quot // and more

خیلی بهتر میشه اگه ما این امکان رو داشته باشیم که یسری محدودیت ها تعریف بکنیم. مثلا بگیم تنها امکان اجرای دستورات focus و blur از طریق inputRef مهیاست و هر دستوری بغیر از این مورد نباید امکان پذیر باشه و برای ما ارور برگردونده بشه.

و این مورد موضوع مورد بحث ما در پست بعدی خواهد بود: useImperativeHandle در react

به پایان این پست رسیدیم. امیدوارم براتون مفید بوده باشه.












reactuseref
سلام دوستان. من امیر امیرپور هستم توسعه دهنده فرانت اند. سعی می کنم اینجا مطالبی مرتبط با این حوزه منتشر کنم.
شاید از این پست‌ها خوشتان بیاید