id | title | permalink | prev | next | redirect_from | |
---|---|---|---|---|---|---|
handling-events |
Események kezelése |
docs/handling-events.html |
state-and-lifecycle.html |
conditional-rendering.html |
|
A React elemek eseményeinek kezelése nagyon hasonló a DOM elemek eseménykezeléséhez. Viszont van néhány szintaxisbeli különbség:
- A React események elnevezésére camelCase-t használunk kisbetűk helyett.
- A JSX-ben string helyett függvényt adunk át az eseménykezelőnek.
Például ez a HTML:
<button onclick="activateLasers()">
Lézerek aktiválása
</button>
kissé máshogyan néz ki Reactben:
<button onClick={activateLasers}>
Lézerek aktiválása
</button>
Egy másik különbség, hogy nem tudsz false
értéket visszaadni, hogy megakadályozd a default viselkedést Reactben. Expliciten meg kell hívni a preventDefault
-ot. Például szimpla HTML-ben ahhoz, hogy megakadályozzuk egy linknek a default viselkedését, ezt írhatjuk:
<a href="#" onclick="console.log('Rákattintottak a linkre.'); return false">
Kattints rám
</a>
Reactben ez így nézne ki:
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('Rákattintottak a linkre.');
}
return (
<a href="#" onClick={handleClick}>
Kattints rám
</a>
);
}
Itt az e
egy szintetikus esemény. A React ezeket a szintetikus eseményeket a W3C specifikáció alapján definiálja, emiatt nem kell a böngészők közötti kompatibilitással törődnöd. Lásd a SyntheticEvent
referenciát, ha többet szeretnél megtudni erről.
Reactben általában nem kell meghívnod az addEventListener
-t hogy eseménykezelőket adj hozzá egy DOM elemhez miután az létrejött. Ehelyett szimplán akkor add hozzá, amikor az elem először renderelődik.
Amikor egy komponenst ES6 osztályként definiálsz, az eseménykezelő általában egy függvény az adott osztályban. Például ez a Toggle
komponens egy gombot renderel, ami az "ON" és "OFF" közötti kapcsolást teszi lehetővé a felhasználó számára:
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// Ez a kötés(binding) szükséges a `this` használatához a callbackben
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
Vigyázni kell a this
használatával a JSX callbackekben. JavaScriptben az osztálymetódusok alapesetben nincsenek hozzákötve a this
-hez. Ha elfelejtenéd hozzákötni a this.handleClick
-et a this
-hez és így rendeled hozzá az onClick
-hez, a this
undefined
értékű lesz amikor a metódus meghívódik.
Ez nem React-specifikus viselkedés, hanem alapvetően így működnek a függvények JavaScriptben. Általában, ha egy metódusra a ()
nélkül hivatkozol, például onClick={this.handleClick}
, hozzá kell kötnöd ezt a metódust a this
-hez.
Ha a bind
hívás zavar téged, kétféle módon is kikerülheted. Ha a kísérleti nyilvános osztálymező szintaxist használod, a kötéshez osztálymezőket is használhatsz:
class LoggingButton extends React.Component {
// Ez a szintaxis biztosítja a `this` handleClickhez kötését.
// Vigyázat: ez *kísérleti* szintaxis.
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Kattints rám
</button>
);
}
}
Ez a szintaxis alapból be van kapcsolva Create React App-ban.
Az osztálymező szintaxis helyett nyilas metódusokat is használhatsz a callbackben:
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// Ez a szintaxis biztosítja a `this` handleClickhez való kötését
return (
<button onClick={(e) => this.handleClick(e)}>
Kattints rám
</button>
);
}
}
Az a probléma ezzel a szintaxissal, hogy a LoggingButton
minden egyes renderelésekor egy új callback hozódik létre. A legtöbb esetben ez nem gond. Viszont ha ezt a callbacket gyerekkomponenseknek adjuk át, azok lehet, hogy még egyszer újrarenderelődnek. Mi általánosságban a konstruktor bindingot vagy az oszálymező szintaxist ajánljuk, hogy elkerüljük az efféle teljesítményproblémákat.
Egy cikluson belül gyakori, hogy egy extra paramétert is szeretnénk átadni egy eseménykezelőnek. Például ha id
a sor azonosítója, a következők bármelyike működhet:
<button onClick={(e) => this.deleteRow(id, e)}>Sor törlése</button>
<button onClick={this.deleteRow.bind(this, id)}>Sor törlése</button>
A fenti két sor ekvivalens, és sorrendben nyilas függvényeket és Function.prototype.bind
-ot használnak.
Mindkét esetben az e
argumentum, ami a React eseményt reprezentálja, az ID után egy második paraméterként lesz átadva. A nyilas függvénnyel explicit módon adjuk át, viszont a bind
használatával minden további argumentum automatikusan átadódik.