So legen Sie den Event-Handler in der React-Unterkomponente fest
-
21-12-2019 - |
Frage
Ich habe Probleme, Menüelemente mit einem Event-Handler zu verbinden.Hier ist eine Nachbildung der Benutzeroberfläche, die Zustandsänderungen im Laufe der Zeit zeigt.Es handelt sich um ein Dropdown-Menü (über Bootstrap), wobei im Stammmenüelement die aktuelle Auswahl angezeigt wird:
[ANN]<click ... [ANN] ... [BOB]<click ... [BOB]
[Ann] [Ann]
[Bob]<click + ajax [Bob]
[Cal] [Cal]
Das Endziel besteht darin, den Seiteninhalt asynchron basierend auf der Auswahl des Benutzers zu ändern.Ein Klick auf Bob sollte das auslösen handleClick
, aber es ist nicht.
Nebenbei bemerkt, ich bin nicht besonders zufrieden mit der Art und Weise, wie „componentDidMount“ aufruft this.handleClick();
, aber es funktioniert vorerst als Möglichkeit, erste Menüinhalte vom Server abzurufen.
/** @jsx React.DOM */
var CurrentSelection = React.createClass({
componentDidMount: function() {
this.handleClick();
},
handleClick: function(event) {
alert('clicked');
// Ajax details ommitted since we never get here via onClick
},
getInitialState: function() {
return {title: "Loading items...", items: []};
},
render: function() {
var itemNodes = this.state.items.map(function (item) {
return <li key={item}><a href='#' onClick={this.handleClick}>{item}</a></li>;
});
return <ul className='nav'>
<li className='dropdown'>
<a href='#' className='dropdown-toggle' data-toggle='dropdown'>{this.state.title}</a>
<ul className='dropdown-menu'>{itemNodes}</ul>
</li>
</ul>;
}
});
$(document).ready(function() {
React.renderComponent(
CurrentSelection(),
document.getElementById('item-selection')
);
});
Ich bin mir fast sicher, dass mein unklares Verständnis des Javascript-Scopings daran schuld ist, aber alles, was ich bisher versucht habe, ist fehlgeschlagen (einschließlich des Versuchs, den Handler durch Requisiten weiterzugeben).
Lösung
Das Problem besteht darin, dass Sie die Elementknoten mithilfe einer anonymen Funktion erstellen, und zwar innerhalb dieser this
Bedeutet die window
.Die Lösung besteht darin, hinzuzufügen .bind(this)
zur anonymen Funktion.
var itemNodes = this.state.items.map(function (item) {
return <li key={item}><a href='#' onClick={this.handleClick}>{item}</a></li>;
}.bind(this));
Oder erstellen Sie eine Kopie von this
und verwenden Sie stattdessen Folgendes:
var _this = this, itemNodes = this.state.items.map(function (item) {
return <li key={item}><a href='#' onClick={_this.handleClick}>{item}</a></li>;
})
Andere Tipps
Da ich die Spezifikation der Aufgabe für „Anna“, „Bob“, „Cal“ nachvollziehen kann, kann die Lösung wie folgt aussehen (basierend auf einer React-Komponente und ES6):
Die grundlegende Live-Demo finden Sie hier
import React, { Component } from "react"
export default class CurrentSelection extends Component {
constructor() {
super()
this.state = {
index: 0
}
this.list = ["Anna", "Bob", "Cal"]
}
listLi = list => {
return list.map((item, index) => (
<li key={index}>
<a
name={item}
href="#"
onClick={e => this.onEvent(e, index)}
>
{item}
</a>
</li>
))
}
onEvent = (e, index) => {
console.info("CurrentSelection->onEvent()", { [e.target.name]: index })
this.setState({ index })
}
getCurrentSelection = () => {
const { index } = this.state
return this.list[index]
}
render() {
return (
<div>
<ul>{this.listLi(this.list)}</ul>
<div>{this.getCurrentSelection()}</div>
</div>
)
}
}