تكامل React مع المكتبات الأخرى
يمكن استخدام React في أي تطبيق ويب وتضمينها في تطبيقات أخرى، ويمكن أيضًا بجهد قليل تضمين المكتبات الأخرى مع React. سنتحدث في هذه الصفحة عن بعض أشيع الحالات مع التركيز على التكامل مع jQuery و Backbone، ولكن يمكن تطبيق نفس الأفكار لتكامل المكوّنات مع أي شيفرة موجودة حاليًّا.
إضافات التكامل مع DOM
لا تعلم React بأي تغيير يحصل على DOM من خارج نطاق React. فهي تُحدِّد التحديثات بناءً على تمثيلها الداخلي الخاص، وإن عدّلت أي مكتبة أخرى على نفس عقدة DOM، فستختلط الأمور مع React ولن تتمكن من إدراك ما يحصل.
لا يعني هذا استحالة أو صعوبة جمع React مع طرق أخرى للتعديل على DOM، ولكن يجب أن تكون على معرفة بما يجري.
أسهل طريقة لتجنب التضاربات هي منع مكوّن React من التحديث. بإمكانك فعل ذلك عن طريق تصيير عناصر لا داع لتحديثها في React، مثل عنصر <div />
الفارغ.
كيفيّة حل المشكلة
لتوضيح هذا فلنصنع حاوية لإضافة jQuery عامّة.
سنضيف مرجع إلى عنصر DOM الجذري. وبداخل التابع componentDidMount
سنحصل على مرجع له لكي نستطيع تمريره إلى إضافة jQuery.
ولمنع React من الاقتراب من DOM بعد الوصل، فسنعيد عنصر <div />
فارغ من التابع render()
، لا يمتلك هذا العنصر أي خاصيّات أو أبناء، لذا لا تملك React سببًا لتحديثه، وبذلك نترك إضافة jQuery حرّة لإدارة ذلك الجزء من DOM:
class SomePlugin extends React.Component {
componentDidMount() {
this.$el = $(this.el);
this.$el.somePlugin();
}
componentWillUnmount() {
this.$el.somePlugin('destroy');
}
render() {
return <div ref={el => this.el = el} />;
}
}
لاحظ أننا عرّفنا توابع دورة الحياة componentDidMount
و componentWillUnmount
. تربط العديد من إضافات jQuery مستمعات للأحداث إلى DOM لذا من الهام فصلها في التابع componentWillUnmount
. إن لم تزودنا الإضافة بطريقة لمسح كل شيء بعد الانتهاء، فيجب عليك إضافة طريقتك الخاصة مع تذكر إزالة أي مستمع للأحداث سجلته الإضافة لمنع أي تسريب في الذاكرة.
التكامل مع إضافة jQuery التي تدعى Chosen
للحصول على مثال أكثر وضوحًا عن هذه المفاهيم فلنكتب تغليف للإضافة Chosen
والتي تضيف حقل الإدخال <select>
.
ملاحظة: لا تعني إمكانيّة فعل ذلك أنّ هذه هي الطريقة الأفضل من أجل تطبيقات React. نشجعك دومًا على استخدام المكوّنات قدر الإمكان، حيث من الأسهل إعادة استخدامها في تطبيقات React وتزوّدنا بتحكّم أكبر في السلوك والمظهر.
فلننظر أولًا إلى تأثير الإضافة Chosen
على DOM.
إن استدعيتها على عقدة DOM لحقل الاختيار <select> فستقرأ الخاصيّات من عقدة DOM الأصليّة، وتخفيها باستخدام التنسيق السطري (inline)، وتُلحِق بعد ذلك عقدة DOM منفصلة مع تمثيلها الخاص بها بعد العنصر <select>
. بعد ذلك تُطلِق أحداث jQuery لتنبيهنا حول التغييرات.
فلنفترض أنّ هذه هي واجهة برمجة التطبيقات (API) التي نرغب بإضافتها مع المكوّن <Chosen>
:
function Example() {
return (
<Chosen onChange={value => console.log(value)}>
<option>vanilla</option>
<option>chocolate</option>
<option>strawberry</option>
</Chosen>
);
}
سننفذها كمكوّن غير مضبوط للسهولة.
سنُنشِئ أولًا مكوّنًا فارغًا مع التابع render()
حيث نعيد الحقل <select>
مُغلَّفًا ضمن عنصر <div>
:
class Chosen extends React.Component {
render() {
return (
<div>
<select className="Chosen-select" ref={el => this.el = el}>
{this.props.children}
</select>
</div>
);
}
}
لاحظ كيف غلّفنا <select> ضمن عنصر <div> إضافي. يكون هذا ضروريًّا لأنّ Chosen ستُلحِق عنصر DOM آخر مباشرةً بعد عقدة العنصر <select> التي مررناها إليها. ولكن على حد علم React فإنّ العنصر <div> يمتلك ابنًا واحدًا فقط. بهذا نضمن عدم تضارب تحديثات React مع عُقَد DOM الإضافية التي تُضيفها Chosen. من الهام عند تعديلك لعقد DOM خارج إطار React أن تضمن ألّا يكون هنالك سبب يجعل React تقترب من عقد DOM هذه.
سننفذ بعد ذلك توابع دورة حياة المكونات، نحتاج إلى تهيئة Chosen بالمرجع إلى عقدة <select> في التابع componentDidMount وحذف هذا المرجع في التابع componentWillUnmount: