التعامل مع DOM باستخدام المراجع (Refs)
يقوم React تلقائيًا بتحديثDOMليطابق ناتج التصيير الخاص بك، لذلك لن تحتاج مكوناتك في كثير من الأحيان إلى التعامل معه مباشرة. ومع ذلك، قد تحتاج أحيانًا إلى الوصول إلى عناصر DOM التي يديرها React — على سبيل المثال، لتركيز التركيز على عقدة، أو التمرير إليها، أو قياس حجمها وموقعها. لا توجد طريقة مضمنة في React للقيام بهذه الأشياء، لذلك ستحتاج إلىمرجع (ref)لعقدة DOM.
سوف تتعلم
- كيفية الوصول إلى عقدة DOM التي يديرها React باستخدام سمة
ref - كيف ترتبط سمة JSX
refبخطاف (Hook)useRef - كيفية الوصول إلى عقدة DOM لمكون آخر
- في أي الحالات يكون من الآمن تعديل DOM الذي يديره React
الحصول على مرجع (ref) للعقدة
للوصول إلى عقدة DOM التي يديرها React، أولاً، قم باستيراد خطاف (Hook)useRef:
ثم، استخدمه لتعريف مرجع (ref) داخل مكونك:
أخيرًا، مرر المرجع (ref) الخاص بك كسمةrefلعلامة JSX التي تريد الحصول على عقدة DOM الخاصة بها:
يُرجع خطاف (Hook)useRefكائنًا يحتوي على خاصية واحدة تسمىcurrent. في البداية، ستكون قيمةmyRef.current هي null. عندما ينشئ React عقدة DOM لهذا العنصر<div>، سيضع React مرجعًا لهذه العقدة فيmyRef.current. يمكنك بعد ذلك الوصول إلى عقدة DOM هذه من خلالمعالجات الأحداث (event handlers)الخاصة بك واستخدامواجهات برمجة التطبيقات (APIs) المدمجة في المتصفحالمعرفة عليها.
مثال: تركيز إدخال نصي
في هذا المثال، سيؤدي النقر على الزر إلى تركيز الإدخال:
لتنفيذ هذا:
- أعلن عن
inputRefباستخدام خطافuseRef. - مرره كـ
<input ref={inputRef}>. هذا يخبر React بأنيضع عقدة DOM الخاصة بـ<input>هذه فيinputRef.current. - في دالة
handleClick، اقرأ عقدة DOM للإدخال منinputRef.currentواستدعِfocus()عليها باستخدامinputRef.current.focus(). - مرر معالج الحدث
handleClickإلى<button>باستخدامonClick.
بينما تعد معالجة DOM هي حالة الاستخدام الأكثر شيوعًا للمراجع، يمكن استخدام خطافuseRefلتخزين أشياء أخرى خارج React، مثل معرفات المؤقتات. على غرار الحالة، تبقى المراجع بين عمليات التصيير. المراجع تشبه متغيرات الحالة التي لا تسبب إعادة التصيير عند تعيينها. اقرأ عن المراجع فيالرجوع إلى القيم باستخدام المراجع.
مثال: التمرير إلى عنصر
يمكن أن يكون لديك أكثر من مرجع واحد في المكون. في هذا المثال، هناك عرض شرائح لثلاث صور. يقوم كل زر بتوسيط صورة عن طريق استدعاء طريقة المتصفحscrollIntoView()على عقدة DOM المقابلة:
الوصول إلى عُقَد DOM الخاصة بمكوّن آخر
مأزق
المراجع (Refs) هي مخرج طوارئ. التلاعب اليدوي بعُقَد DOM الخاصة بمكوّنآخريمكن أن يجعل كودك هشًا.
يمكنك تمرير المراجع من المكوّن الأب إلى المكوّنات الفرعيةتمامًا مثل أي خاصية (prop) أخرى.
في المثال أعلاه، تم إنشاء مرجع في المكوّن الأب،MyForm، وتم تمريره إلى المكوّن الفرعي،MyInput. ثم يمررMyInputالمرجع إلى<input>. لأن<input>هومكوّن مضمن، فإن React يضبط الخاصية.currentللمرجع لتشير إلى عنصر DOM<input>.
المرجعinputRefالذي تم إنشاؤه فيMyFormيشير الآن إلى عنصر DOM<input>الذي أعادهMyInput. يمكن لمعالج النقر الذي تم إنشاؤه فيMyFormالوصول إلىinputRefواستدعاءfocus()لتعيين التركيز على<input>.
متى يربط React المراجع
في React، يتم تقسيم كل تحديث إلىمرحلتين:
- أثناءالتصيير،يستدعي React مكوّناتك لمعرفة ما يجب أن يكون على الشاشة.
- أثناءالتنفيذ (commit)،يطبق React التغييرات على DOM.
بشكل عام، أنتلا تريدالوصول إلى المراجع أثناء التصيير. وهذا ينطبق على المراجع التي تحمل عُقَد DOM أيضًا. أثناء التصيير الأول، لم يتم إنشاء عُقَد DOM بعد، لذا ستكونref.current هي null. وأثناء تصيير التحديثات، لم يتم تحديث عُقَد DOM بعد. لذا فمن المبكر جدًا قراءتها.
يضبط Reactref.currentأثناء التنفيذ (commit). قبل تحديث DOM، يضبط React قيمref.currentالمتأثرة إلىnull. بعد تحديث DOM، يضبطها React فورًا إلى عُقَد DOM المقابلة.
عادةً، ستصل إلى المراجع من معالجات الأحداث.إذا كنت تريد فعل شيء بمرجع، ولكن لا يوجد حدث معين للقيام به فيه، فقد تحتاج إلى Effect. سنناقش Effects في الصفحات التالية.
أفضل الممارسات لمعالجة DOM باستخدام المراجع
المراجع هي مخرج طوارئ. يجب عليك استخدامها فقط عندما تضطر إلى "الخروج من React". تشمل الأمثلة الشائعة على ذلك إدارة التركيز، أو موضع التمرير، أو استدعاء واجهات برمجة تطبيقات المتصفح التي لا يعرضها React.
إذا التزمت بالإجراءات غير التدميرية مثل التركيز والتمرير، فلن تواجه أي مشاكل. ومع ذلك، إذا حاولتتعديلDOM يدويًا، فقد تخاطر بالتضارب مع التغييرات التي يجريها React.
لتوضيح هذه المشكلة، يتضمن هذا المثال رسالة ترحيب وزرين. الزر الأول يقوم بتبديل ظهورها باستخدامالتصيير الشرطي و الحالة، كما تفعل عادةً في React. يستخدم الزر الثانيواجهة برمجة تطبيقات DOM remove()لإزالتها قسرًا من DOM خارج سيطرة React.
جرب الضغط على "التبديل باستخدام setState" عدة مرات. يجب أن تختفي الرسالة وتظهر مرة أخرى. ثم اضغط على "إزالة من DOM". سيؤدي هذا إلى إزالتها قسرًا. أخيرًا، اضغط على "التبديل باستخدام setState":
بعد إزالة عنصر DOM يدويًا، سيؤدي محاولة استخدامsetStateلإظهاره مرة أخرى إلى تعطل. هذا لأنك غيرت DOM، وReact لا يعرف كيفية الاستمرار في إدارته بشكل صحيح.
تجنب تغيير عقد DOM التي يديرها React.يمكن أن يؤدي تعديل العناصر التي يديرها React أو إضافة عناصر فرعية إليها أو إزالتها إلى نتائج مرئية غير متسقة أو تعطل كما في المثال أعلاه.
ومع ذلك، هذا لا يعني أنه لا يمكنك فعل ذلك على الإطلاق. إنه يتطلب الحذر.يمكنك تعديل أجزاء من DOM بأمان ليس لدى Reactسببلتحديثها.على سبيل المثال، إذا كان بعض<div>فارغًا دائمًا في JSX، فلن يكون لدى React سبب للمس قائمة العناصر الفرعية الخاصة به. لذلك، من الآمن إضافة العناصر أو إزالتها يدويًا هناك.
ملخص
- المراجع هي مفهوم عام، ولكن غالبًا ما ستستخدمها للاحتفاظ بعناصر DOM.
- توجه React لوضع عقدة DOM في
myRef.currentعن طريق تمرير<div ref={myRef}>. - عادةً، ستستخدم المراجع للإجراءات غير التدميرية مثل التركيز، أو التمرير، أو قياس عناصر DOM.
- لا يعرض المكون عقد DOM الخاصة به افتراضيًا. يمكنك اختيار عرض عقدة DOM باستخدام خاصية
ref. - تجنب تغيير عقد DOM التي يديرها React.
- إذا قمت بتعديل عقد DOM التي يديرها React، فقم بتعديل الأجزاء التي ليس لدى React سبب لتحديثها.
Try out some challenges
Challenge 1 of 4:Play and pause the video #
In this example, the button toggles a state variable to switch between a playing and a paused state. However, in order to actually play or pause the video, toggling state is not enough. You also need to call play() and pause() on the DOM element for the <video>. Add a ref to it, and make the button work.
For an extra challenge, keep the “Play” button in sync with whether the video is playing even if the user right-clicks the video and plays it using the built-in browser media controls. You might want to listen to onPlay and onPause on the video to do that.
