Event Handling کی ترتیب
React اور DOM دونوں میں event handling کی ترتیب ایک دوسرے سے مشابہت رکھتی ہے لیکن ان دونوں کے لکھنے کا انداز مختلف ہے
- React events کو lowercase کے بجائے camelCase میں لکھا جاتا ہے
- JSX میں آپ event handler کو string کے بجائے function کے طور پر پیش کرتے ہیں
مثلاً یہ HTML
<button onclick="activateLasers()">
Activate Lasers
</button>React میں یوں لکھا جائے گا
<button onClick={activateLasers}> Activate Lasers
</button>Another difference is that you cannot return false to prevent default behavior in React. You must call preventDefault explicitly. For example, with plain HTML, to prevent the default form behavior of submitting, you can write:
<form onsubmit="console.log('You clicked submit.'); return false">
<button type="submit">Submit</button>
</form>وہیں React میں یہ یوں لکھا جا سکتا ہے
function Form() {
function handleSubmit(e) {
e.preventDefault(); console.log('You clicked submit.');
}
return (
<form onSubmit={handleSubmit}>
<button type="submit">Submit</button>
</form>
);
}e یہاں پر ایک synthethic event ہے، ان synthetic events کو React نے W3C spec کو مدنظر رکھتے ہوئے بنایا ہے لہٰذا یہ مختلف براوزروں کے درمیان مطابقت رکھتے ہیں ۔ اس موضوع پہ مزید معلومات حاصل کرنے کے لیے SyntheticEvent سے منسوب گائیڈ کو ملاحظہ فرمائیں
React میں عموماً DOM کے عناصر پر listeners جوڑنے کے لیے addEventListener استعمال نہیں کرنا پڑتا، یہ کافی ہے کہ جب عناصر render ہو تب آپ listener فراہم کر دیں
جب آپ ES6 class کا استعمال کرتے ہوئے جزو بناتے ہیں تو ایک عام طریقہ کار یہ ہے کہ event handler کو اس class کا طریقہ (method) بنا دیا جائے ۔ مثال کے طور پر یہ Toggle جزو ایک بٹن render کر رہا ہے جس سے ایک صارف “ON” اور “OFF” states کے درمیان ٹوگل کر سکتا ہے
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make `this` work in the callback 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')
);آپ کو JSX callbacks میں this کے معنی کا خاص خیال رکھنا پڑے گا، Javascript میں class کے طریقے (methods) پہلے سے bound نہیں ہوتے لہٰذا اگر آپ this.handleClick کو bind کرنا بھول کیے اور اسے onClick میں پاس کر دیا تو this کا حاصل function call کے وقت undefined ہو جائے گا
یہ طرزِ عمل React کی وجہ سے نہیں ہے، یے JavaScript functions کا ایک بنیادی پہلو ہے ۔ عموماً اگر آپ کسی طریقے (method) کو بنا () کے مخاطب کرتے ہیں جیسے مثلاً onClick={this.handleClick}، تو آپ کو اسے bind کرنا چاہیے
اگر bind کا استعمال آپ کو دشوار لگتا ہے تو آپ دو طریقے اختیار کر سکتے ہیں ۔ اگر آپ تجرباتی public class fields syntax کا استعمال کر رہے ہیں تو آپ class fields سے callbacks کو صحیح طریقہ سے bind کر سکتے ہیں
class LoggingButton extends React.Component {
// This syntax ensures `this` is bound within handleClick. // Warning: this is *experimental* syntax. handleClick = () => { console.log('this is:', this); }
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}یہ syntax پہلے سے ہی Create React App میں زیر استعمال ہے
اگر آپ class fields syntax کا استعمال نہیں کر رہے تو آپ callback میں arrow function کا استعمال کر سکتے ہیں
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// This syntax ensures `this` is bound within handleClick return ( <button onClick={() => this.handleClick()}> Click me
</button>
);
}
}اس syntax کی خامی یہ ہے کہ LoggingButton کا ہر ایک render ایک نیا callback بھی بنائے گا، زیادہ تر معاملات میں، یہ ٹھیک ہے۔ حالانکہ اگر اس callback کو ایک prop کے طور پہ نچلے جزو میں پیش کیا جائے تو وہ جزو ایک اضافی re-rendering کر سکتے ہیں ۔ کارکردگی سے متعلق ان مسائل سے بچنے کے لیے ہم آپ کو دو مشورے دیں گے، پہلا constructor میں binding کا استعمال ہے اور دوسرا class fields syntax کا
Event Handlers میں arguments فراہم کرنا
Loop کے اندر event handler میں ایک اضافی parameter فراہم کرنا ایک عام عمل ہے، مثلاً اگر id کو row ID سے نسبت دی جائے تو ان میں سے کوئی بھی طریقہ استعمال میں لایا جا سکتا ہے
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>یہ دونوں ترتیبات برابر ہیں جو کہ arrow functions اور Function.prototype.bind کا استعمال کر رہی ہیں
یہاں e argument ایک React event ہے جو کی ID کے بعد دوسرے argument کی طرح پیش کیا جائے گا، ایک arrow function کے ساتھ ہم اسے واضح طور پر پیش کریں گے جب کہ bind کے استعمال میں باقی arguments خود بخود آگے پیش کر دیئے جائیں گے