معالجة الأحداث في React
تُشبه معالجة الأحداث لعناصر React معالجة الأحداث لعناصر DOM، ولكن هنالك فروق تتعلّق بالصياغة:
- تُسمَّى أحداث React باستخدام حالة الأحرف camelCase (أي عند وجود اسم مؤلف من عدة كلمات نجعل الحرف الأول من الكلمة الأولى بالشكل الصغير أمّا باقي الكلمات نجعل حرفها الأول بالشكل الكبير) بدلًا من استخدام الشكل الصغير للأحرف.
- نُمرِّر في JSX دالة كمُعالِج للأحداث، بدلًا من سلسلة نصيّة.
على سبيل المثال لنأخذ شيفرة HTML التالية:
<button onclick="activateLasers()">
تفعيل الليزر
</button>
تكون الشيفرة السابقة مختلفة قليلًا في React:
<button onClick={activateLasers}>
تفعيل الليزر
</button>
من الفروق الأخرى أنّه لا يمكنك إعادة القيمة false
لمنع السلوك الافتراضي في React، بل يجب عليك أن تستدعي preventDefault
بشكل صريح، فمثلًا في HTML لمنع السلوك الافتراضي للروابط في فتح صفحة جديدة بإمكانك كتابة ما يلي:
<a href="#" onclick="console.log('ضُغِط على الرابط بنجاح'); return false">
اضغط هنا
</a>
أمّا في React فنكتب بدلًا من ذلك ما يلي:
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('ضُغِط على الرابط بنجاح');
}
return (
<a href="#" onClick={handleClick}>
اضغط هنا
</a>
);
}
يُمثِّل المتغيّر e
هنا حدثًا مُصطنعًا، حيث تُعرِّف React هذه الأحداث المُصطنعة وفق معايير W3C، بحيث لا نهتم بمشاكل التوافقيّة بين المتصفحات. للمزيد حول الأحداث المصطنعة انتقل إلى مرجع الأحداث في React.
ينبغي بشكل عام عند استخدام React ألّا تحتاج إلى استدعاء addEventListener
لإضافة مُستمِع للأحداث إلى عنصر DOM بعد إنشائه، وبدلًا من ذلك نُضيف مُستمِعًا للأحداث عند تصيير العنصر (Rendering Element).
عند تعريف المُكوِّنات باستخدام الأصناف هنالك نمط شائع لمعالج الأحداث ليكون تابعًا ضمن الصنف، ففي المثال التالي يعرض المُكوِّن Toggle
زرًّا يُتيح للمستخدم بأن يقلب بين الحالتين "ON"
و "OFF"
:
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// يكون هذا الربط ضروريًّا لكي تعمل this في رد النداء
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
جرِّب هذا المثال على موقع CodePen.
يجب أن تنتبه إلى معنى this
في ردود نداء JSX، ففي JavaScript لا تُربَط توابع الصّنف بشكل افتراضي عن طريق التابع bind()
، وإن نسيت أن تربط وتُمرِّر this.handleClick
إلى onClick
، فستكون قيمة this
غير مُعرَّفة عند استدعاء الدالة.
لا يُعدُّ هذا سلوكًا مرتبطًا بـ React، بل هو جزء من سياق الدوال في JavaScript. بشكل عام إن أشرت إلى التابع بدون استخدام الأقواس () بعده، مثل onClick={this.handleClick}، فيجب أن تربط ذلك التابع.
إن كان استدعاء التابع bind() يزعجك، فهناك طريقتان للالتفاف حول استعماله، إن كنت تستخدم صياغة حقول الصنف العامة التجريبيّة فبإمكانك استخدام حقول الصنف لربط ردود النداء بشكل صحيح: