التحقق من الأنواع باستخدام PropTypes
ملاحظة: انتقلت React.PropTypes
إلى حزمة مختلفة منذ إصدار React v15.5. من فضلك استخدم المكتبة prop-types
بدلًا من ذلك. نُزوِّدك بشيفرة جاهزة لأتمتة هذه العملية.
عندما ينمو تطبيقك قد تلتقط العديد من الأخطاء باستخدام التحقق من الأنواع. بإمكانك استخدام إضافات JavaScript مثل Flow أو TypeScript للتحقّق من كامل تطبيقك، ولكن حتى ولو لم تستخدمها، تمتلك React بعض القدرات المُضمَّنة للتحقّق من الأنواع. لإجراء التحقّق من الأنواع على خاصيّات المُكوّنات بإمكانك تعيين الخاصية propTypes
إليها:
import PropTypes from 'prop-types';
class Greeting extends React.Component {
render() {
return (
<h1>أهلًا {this.props.name}</h1>
);
}
}
Greeting.propTypes = {
name: PropTypes.string
};
تستخرج PropTypes
مجموعة من أدوات التحقّق لتحرص على أن تكون البيانات المستقبلة صحيحة. سنستخدم في هذا المثال PropTypes.string
. عندما نعطي قيمة غير صحيحة للخاصية سيظهر خطأ في نافذة الكونسول. ولأسباب تتعلق بالأداء لا تُستخدَم propTypes
إلا في وضع التطوير.
PropTypes
سنُوثِّق في هذا المثال أدوات التحقّق المختلفة الموجودة:
import PropTypes from 'prop-types';
MyComponent.propTypes = {
// بإمكانك التصريح عن نوع الخاصيّة. افتراضيًّا كل هذه التصاريح اختياريّة
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol,
// أي شيء يُمكِن تصييره: الأعداد، والسلاسل النصيّة، والعناصر، أو حتى مصفوفة (أو قطعة) تحتوي على هذه الأنواع
optionalNode: PropTypes.node,
// عنصر React
optionalElement: PropTypes.element,
// بإمكانك أيضًا التصريح على أنّ الخاصيّة هي نسخة من الصنف
optionalMessage: PropTypes.instanceOf(Message),
// بإمكانك أن تضمن أن تكون خاصيّاتك محدود إلى قيم مُعيّنة عن طريق معاملتها كـ enum
optionalEnum: PropTypes.oneOf(['News', 'Photos']),
// كائن قد يكون واحدًا من عدّة أنواع
optionalUnion: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.instanceOf(Message)
]),
// مصفوفة من نوع مُحدّد
optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
// كائن من قيم خاصيّات ذات نوع مُحدّد
optionalObjectOf: PropTypes.objectOf(PropTypes.number),
// كائن يتخذ شكلًا مُحدّدًا
optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number
}),
// بإمكانك إضافة isRequired إلى أي من الأمثلة السابقة لإعطاء تحذير إن لم تعطى الخاصيّة
requiredFunc: PropTypes.func.isRequired,
// قيمة من أي نوع من البيانات
requiredAny: PropTypes.any.isRequired,
// بإمكانك أيضًا تحديد أداة تحقق مخصصة. ينبغي أن تعيد كائن يحتوي على الخطأ إن فشل التحقّق.
// لا تستخدم console.warn أو الكلمة throw
// حيث لن يعمل هذا بداخل 'oneOfType'
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error(
'خاصيّة خاطئة `' + propName + '` معطاة إلى' +
' `' + componentName + '`. فشل التحقق'
);
}
},
// بإمكانك أيضًا تزويد أداة تحقق مخصصة من أجل 'arrayOf' و 'objectOf'
// ينبغي أن تعيد كائن يحتوي على الخطأ إن فشل التحقق
// ستستدعى أداة التحقق لكل مفتاح في المصفوفة أو الكائن.
// أول وسيطين من أداة التحقق هما المصفوفة أو الكائن ومفتاح العنصر الحالي
customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
if (!/matchme/.test(propValue[key])) {
return new Error(
'خاصيّة خاطئة `' + propFullName + '` معطاة إلى' +
' `' + componentName + '`. فشل التحقق'
);
}
})
};
تمرير عنصر ابن وحيد
نستطيع باستخدام PropTypes.element
أن نُحدِّد إمكانية تمرير عنصر ابن وحيد للمُكوِّن:
import PropTypes from 'prop-types';
class MyComponent extends React.Component {
render() {
// يجب أن يكون هذا عنصرًا واحدًا فقط أو سيظهر تحذير
const children = this.props.children;
return (
<div>
{children}
</div>
);
}
}
MyComponent.propTypes = {
children: PropTypes.element.isRequired
};
إن كنت تستخدم إضافات التحويل في Babel مثل transform-class-properties
فباستطاعتك التصريح عن defaultProps
كخاصية ثابتة بداخل صنف مُكوِّن React، ومع ذلك هذه الصياغة غير مكتملة وتتطلب خطوة للتصريف لتعمل بداخل المتصفح. للمزيد من المعلومات انظر إلى proposal-class-fields
:
class Greeting extends React.Component {
static defaultProps = {
name: 'غريب'
}
render() {
return (
<div>أهلًا {this.props.name}</div>
)
}
}
تُستخدَم defaultProps
في المثال السابق لتضمن وجود قيمة افتراضية للخاصية this.props.name
إن لم يُحدِّدها المكون الأب. يحصل التحقّق من الأنواع باستخدام PropTypes
بعد إضافة القيم الافتراضيّة defaultProps
لذلك يُطبَّق عليها أيضًا.