web-dev-qa-db-ja.com

React: "this"はコンポーネント関数内では定義されていません

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はコンポーネントを参照するべきです。私は何かが足りないのですか?

101
Maximus S

ES6 React.Componentは、メソッドをそれ自体に自動バインドすることはありません。あなたはそれらをコンストラクタで自分でバインドする必要があります。このような:

constructor (props){
  super(props);

  this.state = {
      loopActive: false,
      shuffleActive: false,
    };

  this.onToggleLoop = this.onToggleLoop.bind(this);

}
161
Ivan

いくつかの方法があります。

1つはコンストラクタにthis.onToggleLoop = this.onToggleLoop.bind(this);を追加することです。

もう1つは矢印関数onToggleLoop = (event) => {...}です。

そしてonClick={this.onToggleLoop.bind(this)}があります。

73
J. Mark Stevens

あなたの関数をこのように書く:

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))。

15
ShaTin

私はレンダー関数で同様のバインドに遭遇し、次のようにしてthisのコンテキストを渡しました。

{someList.map(function(listItem) {
  // your code
}, this)}

私はまた使用しました:

{someList.map((listItem, index) =>
    <div onClick={this.someFunction.bind(this, listItem)} />
)}
9
duhaime

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>
    )
  }

}
1
Henry Jacob

ComponentDidMount ...などのライフサイクルメソッドで作成したメソッドを呼び出す場合は、this.onToggleLoop = this.onToogleLoop.bind(this)と太い矢印関数onToggleLoop = (event) => {...}のみを使用できます。

ライフサイクルメソッドは以前に呼び出されるため、コンストラクターで関数を宣言するという通常の方法ではうまくいきません。

0
Guchelkaben