دليل شامل لـ React forwardRef، يغطي الغرض منه، التنفيذ، حالات الاستخدام، وأفضل الممارسات لإنشاء مكونات React قابلة لإعادة الاستخدام والصيانة بشكل كبير.
React forwardRef: إتقان تمرير المرجع للمكونات القابلة لإعادة الاستخدام
في عالم React، يعد إنشاء مكونات قابلة لإعادة الاستخدام والتركيب أمرًا بالغ الأهمية. ومع ذلك، تحتاج أحيانًا إلى الوصول إلى عقدة DOM الأساسية لمكون فرعي من مكونه الأصلي. هنا يأتي دور React.forwardRef
لإنقاذ الموقف. سيغوص هذا الدليل الشامل في تعقيدات forwardRef
، موضحًا الغرض منه، وتطبيقه، وحالات استخدامه، وأفضل الممارسات.
ما هو تمرير المرجع (Ref Forwarding)؟
تمرير المرجع هو تقنية في React تسمح للمكون الأصلي بالوصول إلى عقدة DOM أو نسخة مكون React لمكون فرعي. في جوهره، يقوم "بتمرير" مرجع (ref) تم إرساله إلى مكون ما إلى أحد أبنائه. يكون هذا مفيدًا بشكل خاص عندما تحتاج إلى التعامل مع DOM لمكون فرعي مباشرةً، مثل التركيز على حقل إدخال أو قياس أبعاده.
بدون forwardRef
، يمكن إرفاق المراجع مباشرةً بعناصر DOM أو مكونات الفئة (class components) فقط. لا يمكن للمكونات الوظيفية (Functional components) استقبال المراجع أو كشفها مباشرةً.
لماذا نستخدم forwardRef
؟
تتطلب العديد من السيناريوهات استخدام forwardRef
:
- التعامل مع DOM: عندما تحتاج إلى التفاعل مباشرة مع DOM لمكون فرعي. على سبيل المثال، ضبط التركيز على حقل إدخال، أو تشغيل الرسوم المتحركة، أو قياس العناصر.
- التجريد (Abstraction): عند إنشاء مكونات واجهة مستخدم قابلة لإعادة الاستخدام تحتاج إلى كشف عناصر DOM معينة للتخصيص أو التكامل مع أجزاء أخرى من التطبيق.
- المكونات عالية الرتبة (HOCs): عند تغليف مكون بـ HOC وتحتاج إلى التأكد من تمرير المراجع بشكل صحيح إلى المكون الأساسي.
- مكتبات المكونات: عند بناء مكتبات المكونات، يتيح تمرير المرجع للمطورين الوصول إلى عناصر DOM الأساسية لمكوناتك وتخصيصها، مما يوفر مرونة أكبر.
كيف يعمل forwardRef
React.forwardRef
هو مكون عالي الرتبة (HOC) يقبل دالة عرض (rendering function) كوسيط له. تستقبل دالة العرض هذه props
و ref
كوسائط. ثم تعيد دالة العرض عنصر React. الوسيط ref
هو المرجع الذي تم تمريره إلى المكون من أصله. يمكنك بعد ذلك إرفاق هذا المرجع بمكون فرعي داخل دالة العرض.
إليك تفصيل للعملية:
- يقوم المكون الأصلي بإنشاء مرجع باستخدام
useRef
. - يقوم المكون الأصلي بتمرير المرجع إلى مكون فرعي كخاصية (prop).
- يتم تغليف المكون الفرعي في
React.forwardRef
. - داخل دالة العرض الخاصة بـ
forwardRef
، يتم إرفاق المرجع بعنصر DOM أو مكون React آخر. - يمكن للمكون الأصلي الآن الوصول إلى عقدة DOM أو نسخة المكون من خلال المرجع.
تنفيذ forwardRef
: مثال عملي
دعنا نوضح forwardRef
بمثال بسيط: مكون إدخال مخصص يسمح للمكون الأصلي بالتركيز على حقل الإدخال برمجيًا.
مثال: مكون إدخال مخصص مع تمرير المرجع
أولاً، لنقم بإنشاء مكون الإدخال المخصص:
import React, { forwardRef } from 'react';
const CustomInput = forwardRef((props, ref) => {
return (
<div>
<label htmlFor={props.id}>{props.label}</label>
<input type="text" id={props.id} ref={ref} {...props} />
</div>
);
});
CustomInput.displayName = "CustomInput"; // يوصى به لتصحيح أخطاء أفضل
export default CustomInput;
في هذا المثال:
- نستورد
forwardRef
من 'react'. - نغلف مكوننا الوظيفي بـ
forwardRef
. - تستقبل دالة
forwardRef
props
وref
كوسائط. - نرفق
ref
بعنصر<input>
. - نضبط
displayName
لتصحيح أخطاء أفضل في React DevTools.
الآن، لنر كيف نستخدم هذا المكون في مكون أصلي:
import React, { useRef, useEffect } from 'react';
import CustomInput from './CustomInput';
const ParentComponent = () => {
const inputRef = useRef(null);
useEffect(() => {
// التركيز على حقل الإدخال عند تحميل المكون
if (inputRef.current) {
inputRef.current.focus();
}
}, []);
return (
<div>
<CustomInput label="الاسم:" id="name" ref={inputRef} placeholder="أدخل اسمك" />
</div>
);
};
export default ParentComponent;
في هذا المكون الأصلي:
- أنشأنا مرجعًا باستخدام
useRef
. - مررنا
inputRef
إلى مكونCustomInput
كخاصيةref
. - داخل خطاف
useEffect
، نصل إلى عقدة DOM الأساسية باستخدامinputRef.current
ونستدعي دالةfocus()
.
عندما يتم تحميل ParentComponent
، سيتم التركيز تلقائيًا على حقل الإدخال في مكون CustomInput
.
حالات استخدام forwardRef
فيما يلي بعض حالات الاستخدام الشائعة حيث يثبت forwardRef
قيمته:
1. التركيز على حقول الإدخال
كما هو موضح في المثال أعلاه، يسمح لك forwardRef
بالتركيز برمجيًا على حقول الإدخال، وهو أمر مفيد للتحقق من صحة النماذج، وإمكانية الوصول، وتحسينات تجربة المستخدم. على سبيل المثال، بعد أن يرسل المستخدم نموذجًا به أخطاء، يمكنك التركيز على أول حقل إدخال به خطأ لتوجيه المستخدم.
2. قياس أبعاد العنصر
يمكنك استخدام forwardRef
للوصول إلى عقدة DOM لمكون فرعي وقياس أبعاده (العرض، الارتفاع، إلخ). هذا مفيد لإنشاء تخطيطات سريعة الاستجابة، وتغيير الحجم الديناميكي، والرسوم المتحركة المخصصة. قد تحتاج إلى قياس ارتفاع منطقة محتوى ديناميكي لضبط تخطيط العناصر الأخرى على الصفحة.
3. التكامل مع مكتبات الطرف الثالث
تتطلب العديد من مكتبات الطرف الثالث الوصول المباشر إلى عقد DOM للتهيئة أو التكوين. يسمح لك forwardRef
بدمج هذه المكتبات بسلاسة مع مكونات React الخاصة بك. تخيل استخدام مكتبة رسوم بيانية تتطلب عنصر DOM كهدف لعرض الرسم البياني. يمكّنك forwardRef
من توفير عنصر DOM هذا للمكتبة.
4. إنشاء مكونات يمكن الوصول إليها
غالبًا ما تتطلب إمكانية الوصول معالجة مباشرة لسمات DOM أو إدارة التركيز. يمكن استخدام forwardRef
لإنشاء مكونات يمكن الوصول إليها وتلتزم بمعايير إمكانية الوصول. على سبيل المثال، قد تحتاج إلى تعيين السمة aria-describedby
على حقل إدخال لربطه برسالة خطأ. يتطلب هذا الوصول المباشر إلى عقدة DOM الخاصة بحقل الإدخال.
5. المكونات عالية الرتبة (HOCs)
عند إنشاء HOCs، من المهم التأكد من تمرير المراجع بشكل صحيح إلى المكون المغلف. يساعدك forwardRef
على تحقيق ذلك. لنفترض أن لديك HOC يضيف تنسيقًا إلى مكون. يضمن استخدام forwardRef
أن أي مراجع يتم تمريرها إلى المكون المنسق يتم تمريرها إلى المكون الأساسي.
أفضل الممارسات لاستخدام forwardRef
لضمان استخدامك لـ forwardRef
بفعالية، ضع في اعتبارك هذه الممارسات الأفضل:
1. استخدم displayName
لتصحيح الأخطاء
قم دائمًا بتعيين خاصية displayName
على مكونات forwardRef
الخاصة بك. هذا يجعل من السهل التعرف عليها في React DevTools. على سبيل المثال:
CustomInput.displayName = "CustomInput";
2. كن على دراية بالأداء
على الرغم من أن forwardRef
أداة قوية، إلا أنها يمكن أن تؤثر على الأداء إذا تم استخدامها بشكل مفرط. تجنب التعامل غير الضروري مع DOM وقم بتحسين منطق العرض الخاص بك. قم بتحليل أداء تطبيقك لتحديد أي اختناقات في الأداء تتعلق بتمرير المرجع.
3. استخدم المراجع بحكمة
لا تستخدم المراجع كبديل لتدفق البيانات في React. يجب استخدام المراجع باعتدال وفقط عند الضرورة للتعامل مع DOM أو التكامل مع مكتبات الطرف الثالث. اعتمد على الخصائص (props) والحالة (state) لإدارة بيانات المكون وسلوكه.
4. وثّق مكوناتك
وثّق بوضوح متى ولماذا تستخدم forwardRef
في مكوناتك. هذا يساعد المطورين الآخرين على فهم الكود الخاص بك واستخدام مكوناتك بشكل صحيح. قم بتضمين أمثلة حول كيفية استخدام المكون والغرض من المرجع الذي يتم تمريره.
5. فكر في البدائل
قبل استخدام forwardRef
، فكر فيما إذا كانت هناك حلول بديلة قد تكون أكثر ملاءمة. على سبيل المثال، قد تكون قادرًا على تحقيق السلوك المطلوب باستخدام الخصائص والحالة بدلاً من التعامل المباشر مع DOM. استكشف الخيارات الأخرى قبل اللجوء إلى forwardRef
.
بدائل forwardRef
بينما يكون forwardRef
غالبًا هو الحل الأفضل لتمرير المراجع، هناك طرق بديلة قد تفكر فيها في مواقف معينة:
1. المراجع المرتجعة (Callback Refs)
توفر المراجع المرتجعة طريقة أكثر مرونة للوصول إلى عقد DOM. بدلاً من تمرير خاصية ref
، يمكنك تمرير دالة تستقبل عقدة DOM كوسيط. يتيح لك هذا تنفيذ منطق مخصص عند إرفاق عقدة DOM أو فصلها. ومع ذلك، يمكن أن تكون المراجع المرتجعة أكثر تفصيلاً وأقل قابلية للقراءة من forwardRef
.
const MyComponent = () => {
let inputElement = null;
const setInputElement = (element) => {
inputElement = element;
};
useEffect(() => {
if (inputElement) {
inputElement.focus();
}
}, []);
return <input type="text" ref={setInputElement} />;
};
2. التركيب (Composition)
في بعض الحالات، يمكنك تحقيق السلوك المطلوب عن طريق تركيب المكونات بدلاً من استخدام forwardRef
. يتضمن ذلك تقسيم مكون معقد إلى مكونات أصغر وأكثر قابلية للإدارة وتمرير البيانات والسلوك بينها باستخدام الخصائص. يمكن أن يؤدي التركيب إلى كود أكثر قابلية للصيانة والاختبار، ولكنه قد لا يكون مناسبًا لجميع السيناريوهات.
3. خصائص العرض (Render Props)
تسمح لك خصائص العرض بمشاركة الكود بين مكونات React باستخدام خاصية تكون قيمتها دالة. يمكنك استخدام خصائص العرض لكشف عقد DOM أو نسخ المكونات للمكون الأصلي. ومع ذلك، يمكن أن تجعل خصائص العرض الكود الخاص بك أكثر تعقيدًا وصعوبة في القراءة، خاصة عند التعامل مع خصائص عرض متعددة.
أخطاء شائعة يجب تجنبها
عند العمل مع forwardRef
، من المهم تجنب هذه الأخطاء الشائعة:
1. نسيان تعيين displayName
كما ذكرنا سابقًا، يمكن أن يؤدي نسيان تعيين خاصية displayName
إلى صعوبة تصحيح الأخطاء. قم دائمًا بتعيين displayName
لمكونات forwardRef
الخاصة بك.
2. الإفراط في استخدام المراجع
قاوم إغراء استخدام المراجع لكل شيء. يجب استخدام المراجع باعتدال وفقط عند الضرورة للتعامل مع DOM أو التكامل مع مكتبات الطرف الثالث. اعتمد على الخصائص والحالة لإدارة بيانات المكون وسلوكه.
3. التعامل مع DOM مباشرة بدون سبب وجيه
يمكن أن يجعل التعامل المباشر مع DOM الكود الخاص بك أصعب في الصيانة والاختبار. تعامل مع DOM فقط عند الضرورة القصوى وتجنب تحديثات DOM غير الضرورية.
4. عدم التعامل مع المراجع الفارغة (Null Refs)
تحقق دائمًا مما إذا كان المرجع فارغًا (null) قبل الوصول إلى عقدة DOM الأساسية أو نسخة المكون. هذا يمنع الأخطاء عندما لا يكون المكون قد تم تحميله بعد أو تم إلغاء تحميله.
if (inputRef.current) {
inputRef.current.focus();
}
5. إنشاء تبعيات دائرية
كن حذرًا عند استخدام forwardRef
مع تقنيات أخرى مثل HOCs أو خصائص العرض. تجنب إنشاء تبعيات دائرية بين المكونات، حيث يمكن أن يؤدي ذلك إلى مشكلات في الأداء أو سلوك غير متوقع.
أمثلة من جميع أنحاء العالم
مبادئ React و forwardRef
عالمية، ولكن فكر في كيفية قيام المطورين من مناطق مختلفة بتكييف استخدامها:
- التوطين والتدويل (i18n): قد يستخدم المطورون الذين يبنون تطبيقات متعددة اللغات في أوروبا أو آسيا
forwardRef
لقياس حجم عناصر النص المترجمة لضبط التخطيطات ديناميكيًا للغات مختلفة، مما يضمن عدم تجاوز النص للحاويات. على سبيل المثال، تميل الكلمات الألمانية إلى أن تكون أطول من الكلمات الإنجليزية، مما يتطلب تعديلات. - تخطيطات من اليمين إلى اليسار (RTL): في الشرق الأوسط وأجزاء من آسيا، غالبًا ما تحتاج التطبيقات إلى دعم تخطيطات RTL. يمكن استخدام
forwardRef
لضبط موضع العناصر برمجيًا بناءً على اتجاه التخطيط الحالي. - إمكانية الوصول للمستخدمين المتنوعين: على الصعيد العالمي، تعد إمكانية الوصول مصدر قلق متزايد. قد يستخدم المطورون
forwardRef
لتعزيز إمكانية الوصول للمستخدمين ذوي الإعاقة، مثل التركيز برمجيًا على العناصر لقارئات الشاشة أو ضبط ترتيب التنقل (tab order) في حقول النماذج. - التكامل مع واجهات برمجة التطبيقات الخاصة بالمنطقة: قد يستخدم المطورون الذين يتكاملون مع واجهات برمجة التطبيقات المحلية (مثل بوابات الدفع، وخدمات الخرائط)
forwardRef
للوصول إلى عناصر DOM التي تتطلبها تلك الواجهات، مما يضمن التوافق والتكامل السلس.
الخاتمة
React.forwardRef
هي أداة قوية لإنشاء مكونات React قابلة لإعادة الاستخدام والتركيب. من خلال السماح للمكونات الأصلية بالوصول إلى عقد DOM أو نسخ المكونات لأبنائها، يتيح forwardRef
مجموعة واسعة من حالات الاستخدام، من التعامل مع DOM إلى التكامل مع مكتبات الطرف الثالث. باتباع أفضل الممارسات الموضحة في هذا الدليل، يمكنك الاستفادة من forwardRef
بفعالية وتجنب الأخطاء الشائعة. تذكر استخدام المراجع بحكمة، وتوثيق مكوناتك بوضوح، والنظر في الحلول البديلة عند الاقتضاء. مع فهم قوي لـ forwardRef
، يمكنك بناء تطبيقات React أكثر قوة ومرونة وقابلية للصيانة.