class PlayerControls extends React.Component {
constructor(props) {
super(props)
this.state = {
loopActive: false,
shuffleActive: false,
}
}
render() {
var shuffleClassName = this.state.toggleActive ? "player-control-icon active" : "player-control-icon"
return (
<div className="player-controls">
<FontAwesome
className="player-control-icon"
name='refresh'
onClick={this.onToggleLoop}
spin={this.state.loopActive}
/>
<FontAwesome
className={shuffleClassName}
name='random'
onClick={this.onToggleShuffle}
/>
</div>
);
}
onToggleLoop(event) {
// "this is undefined??" <--- here
this.setState({loopActive: !this.state.loopActive})
this.props.onToggleLoop()
}
トグル時にloopActive
の状態を更新したいのですが、this
オブジェクトはハンドラ内で未定義です。チュートリアルのドキュメントによると、this
はコンポーネントを参照するべきです。私は何かが足りないのですか?
ES6 React.Componentは、メソッドをそれ自体に自動バインドすることはありません。あなたはそれらをコンストラクタで自分でバインドする必要があります。このような:
constructor (props){
super(props);
this.state = {
loopActive: false,
shuffleActive: false,
};
this.onToggleLoop = this.onToggleLoop.bind(this);
}
いくつかの方法があります。
1つはコンストラクタにthis.onToggleLoop = this.onToggleLoop.bind(this);
を追加することです。
もう1つは矢印関数onToggleLoop = (event) => {...}
です。
そしてonClick={this.onToggleLoop.bind(this)}
があります。
あなたの関数をこのように書く:
onToggleLoop = (event) => {
this.setState({loopActive: !this.state.loopActive})
this.props.onToggleLoop()
}
http://www.react.express/fat_arrow_functions
キーワードthisの束縛は太い矢印関数の外側と内側で同じです。これは、呼び出し時にこれを別のオブジェクトにバインドできるfunctionで宣言された関数とは異なります。 thisバインディングを維持することはマッピングのような操作にとても便利です:this.items.map(x => this.doSomethingWith(x))。
私はレンダー関数で同様のバインドに遭遇し、次のようにしてthis
のコンテキストを渡しました。
{someList.map(function(listItem) {
// your code
}, this)}
私はまた使用しました:
{someList.map((listItem, index) =>
<div onClick={this.someFunction.bind(this, listItem)} />
)}
Babelを使用している場合は、ES7バインド演算子 を使用して「this」をバインドします。結合
export default class SignupPage extends React.Component {
constructor(props) {
super(props);
}
handleSubmit(e) {
e.preventDefault();
const data = {
email: this.refs.email.value,
}
}
render() {
const {errors} = this.props;
return (
<div className="view-container registrations new">
<main>
<form id="sign_up_form" onSubmit={::this.handleSubmit}>
<div className="field">
<input ref="email" id="user_email" type="email" placeholder="Email" />
</div>
<div className="field">
<input ref="password" id="user_password" type="new-password" placeholder="Password" />
</div>
<button type="submit">Sign up</button>
</form>
</main>
</div>
)
}
}
ComponentDidMount ...などのライフサイクルメソッドで作成したメソッドを呼び出す場合は、this.onToggleLoop = this.onToogleLoop.bind(this)
と太い矢印関数onToggleLoop = (event) => {...}
のみを使用できます。
ライフサイクルメソッドは以前に呼び出されるため、コンストラクターで関数を宣言するという通常の方法ではうまくいきません。