لینک این پست به زبان انگلیسی در لینکدین
چه مطالبی گفته خواهد شد:
شما احتمالا با مفهوم ref در react آشنایی دارید. ما در react می توانیم به المان های DOM از طریق ref دسترسی داشته باشیم.(البته این تنها کاربرد ref در react نیست ولی یکی از رایج ترین موارد مورد استفاده از ref می باشد.)
قطعه کد پایین را مشاهده بفرمایید:
در اینجا inputRef برای ما آبجکتی شامل تنها یک کلید به نام current را برمی گرداند.
شما می توانید inputRef را مانند زیر در نظر بگیرید:
const inputRef = { current: some_value };
در اینجا ما می توانیم از طریق inputRef.current به المان input دسترسی داشته باشیم و هر کد جاوااسکریپتی قابل قبول را روش اجرا کنیم.
به عنوان مثال تصور کنید یک button وجود داره و ما می خواهیم با کلیک بر روی این button المان input ما در وضعیت focus قرار بگیره. قطعه کد زیر این کار رو انجام میده:
تا اینجا همه چیز به درستی داره کار می کنه اما فرض کنید ما بخواهیم بجای المان input از یک کامپوننت react که خودمون نوشتیم استفاده بکنیم. فرض کنید ما کامپوننتی به نام Input در پروژه خودمون ایجاد کردیم.
لطفا دقت کنید که input با Input تفاوت دارد. input یک المان HTML هست ولی Input یک کامپوننت react هست که ممکنه داخلش شامل چندین المان HTML باشه.
<input /> actual HTML element <Input /> react component
قطعه کد زیر را مشاهده کنید که داخلش ما کامپوننت Input خودمون رو تعریف کردیم:
حالا در فایل App.jsx بجای تگ input از کامپوننتی که نوشتیم استفاده می کنیم. قطعه کد زیر رو مشاهده کنید:
اینجا تنها تغییر اینه که ما داریم از کامپوننتی که خودمون نوشتیم بجای تگ input استفاده می کنیم.
بنظرتون کد هنوز هم مثل قبل به درستی کار میکنه ؟
(راهنمایی:اگه کد همچنان به درستی کار بکنه این پست بی فایده خواهد بود)
از اونجایی که این پست قرار نیست بی فایده باشه ? (حداقل جوری که من فکر می کنم) جواب سوال قبل اینه که خیر با تغییری که ما دادیم کد الان به مشکل خورده و مثل قبل کار نمی کنه.
در واقع اگر الان داخل کامپوننت Input دستور console.log(props.ref) رو اجرا کنیم مقدار undefined رو خواهیم دید.
چـــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــــرا این اتفاق افتاد ؟
خب علت اینه که در react به طور پیش فرض یک کامپوننت اجازه دسترسی به المان های DOM کامپوننت های دیگه نداره. در بیشتر مواقع این اتفاق دقیقا چیزی هست که مورد نیاز ما هست ولی در بعضی مواقع مشابه مثال ما نیاز داریم که یک کامپوننت خاص اجازه دسترسی به بعضی از المان های DOM خودش رو به بقیه کامپوننت ها بده.
برای این کار ما باید خودمون این مورد رو ذکر کنیم.
حالا ما چطور به react بگیم که یکی از کامپوننت های ما مثلا در اینجا Input می خواد اجازه دسترسی به المان input خودش رو به سایر کامپوننت ها بده ؟
(راهنمایی: نگاهی به عنوان این پست بندازید.)
ما در اینجا نیاز به استفاده از forwardRef داریم. در واقع کاری که ما باید بکنیم اینه که inputRef رو به عنوان prop با نام ref به کامپوننت Input پاس بدیم و بعد این ref رو فوروارد کنیم به تگ input که داریم داخل کامپوننت Input رندر می کنیم.
قطعه کد زیر رو مشاهده کنید:
همانطور که مشاهده می کنید تابع forwardRef ابجکت props رو به عنوان آرگومان اول و ref رو به عنوان آرگومان دوم دریافت می کنه. حالا ما می تونیم تعیین کنیم کجا می خواهیم از این ref استفاده کنیم که ما هم این ref رو به تگ input دادیم.
حالا اگر شما دستور console.log(ref) رو در فایل Input.jsx چاپ کنید دیگه مقدار undefined رو نخواهید دید و میتونید هر طور که می خواهید از این ref استفاده کنید.
به کد های زیر نگاهی بندازید که ورژن نهایی هر دو فایل مورد استفاده(App.jsx و Input.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 = "10rem" inputRef.current.style.display = "none" // and more
خیلی بهتر میشه اگه ما این امکان رو داشته باشیم که یسری محدودیت ها تعریف بکنیم. مثلا بگیم تنها امکان اجرای دستورات focus و blur از طریق inputRef مهیاست و هر دستوری بغیر از این مورد نباید امکان پذیر باشه و برای ما ارور برگردونده بشه.
و این مورد موضوع مورد بحث ما در پست بعدی خواهد بود: useImperativeHandle در react
به پایان این پست رسیدیم. امیدوارم براتون مفید بوده باشه.