React-キャッチされないTypeError:未定義のプロパティ 'setState'を読み取れません


316

次のエラーが発生します

Uncaught TypeError:未定義のプロパティ 'setState'を読み取れません

コンストラクタでデルタをバインドした後でも。

class Counter extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            count : 1
        };

        this.delta.bind(this);
    }

    delta() {
        this.setState({
            count : this.state.count++
        });
    }

    render() {
        return (
            <div>
                <h1>{this.state.count}</h1>
                <button onClick={this.delta}>+</button>
            </div>
        );
    }
}

4
ES6では、関数の宣言にアロー関数を使用して、この問題を修正できます。
Tal

^これが正しい答えでなければなりません
Jordec

応答関数をES6に変更しました。
Ashwani Garg

回答:


449

これは、this.deltaにバインドされていないためthisです。

this.delta = this.delta.bind(this)コンストラクターでセットをバインドするには:

constructor(props) {
    super(props);

    this.state = {
        count : 1
    };

    this.delta = this.delta.bind(this);
}

現在、bindを呼び出しています。ただし、bindはバインドされた関数を返します。関数をそのバインドされた値に設定する必要があります。


187
ES6クラスのポイントは、メソッドに適切な字句thisバインディングがなく、コンテキストを定義に直接バインドするための構文を公開していない場合、一体何が重要なのでしょうか。
AgmLauncher 2016年

1
私はあなたのポイントを理解していますが、componentWillMount()でコードを書いた場合、どのようにバインドしますか
シュレッシュパリーク

1
@sureshpareekコンストラクターで関数をバインドしたら、ライフサイクルフックから呼び出すときに関数をバインドする必要があります。
Levi Fuller

4
私は困惑しているandroid / javaの世界から来る
Tudor

3
@AgmLauncherがLambda関数を使用すると、暗黙的にバインドされます。コードdeltaとして定義しdelta = () => { return this.setState({ count: this.state.count++ }); };た場合も機能します。ここで説明: hackernoon.com/...
K.ローダ

145

ES7 +(ES2016)あなたは、実験に使用できる機能バインド構文演算子を::バインドします。これは構文糖であり、Davin Tryonの答えと同じです。

その後、書き換え可能this.delta = this.delta.bind(this);this.delta = ::this.delta;


ES6 +(ES2015)あなたもES6 +を使用することができる機能ARROW=>使用できるようにします)this

delta = () => {
    this.setState({
        count : this.state.count + 1
    });
}

どうして ?Mozilla docから:

アロー関数までは、すべての新しい関数が独自のthis値を定義していました[...]。これは、オブジェクト指向のプログラミングスタイルでは煩わしいことがわかりました。

矢印関数は、囲んでいるコンテキストのthis値をキャプチャします[...]


3
これを詳細に記述したニースの記事:reactkungfu.com/2015/07/...
江戸

構文以外に、どちらを使用する利点は何ですか?
Jeremy D

2
メソッドの通常のスコープを維持できるため、バインド構文はより簡潔です。
Fabien Sa

バインド構文は、ES2016またはES2017の一部ではありません。
Felix Kling 2017

2
@stackoverflowは、任意の回答に賞金を追加する機能を追加する必要があります。
Gabe

29

ES5クラスとES6クラスにはコンテキストの違いがあります。したがって、実装にも少し違いがあります。

ES5のバージョンは次のとおりです。

var Counter = React.createClass({
    getInitialState: function() { return { count : 1 }; },
    delta: function() {
        this.setState({
            count : this.state.count++
        });
    },
    render: function() {
        return (
            <div>
              <h1>{this.state.count}</h1>
              <button onClick={this.delta}>+</button>
            </div>
            );
    }
});

ES6のバージョンは次のとおりです。

class Counter extends React.Component {
    constructor(props) {
        super(props);
        this.state = { count : 1 };
    }

    delta() {
        this.setState({
            count : this.state.count++
        });
    }

    render() {
        return (
            <div>
              <h1>{this.state.count}</h1>
              <button onClick={this.delta.bind(this)}>+</button>
            </div>
            );
    }
}

ただ注意してください。クラス実装の構文の違いに加えて、イベントハンドラーバインディングにも違いがあります。

ES5バージョンでは、

              <button onClick={this.delta}>+</button>

ES6バージョンでは、次のとおりです。

              <button onClick={this.delta.bind(this)}>+</button>

JSXで矢印関数またはバインディングを使用することは悪い習慣です。stackoverflow.com/questions/36677733/…
Fabien Sa、

24

ReactでES6コードを使用する場合、thisコンテキストは自動的にバインドされるため、常に矢印関数を使用します。

これを使って:

(videos) => {
    this.setState({ videos: videos });
    console.log(this.state.videos);
};

の代わりに:

function(videos) {
    this.setState({ videos: videos });
    console.log(this.state.videos);
};

2
アロー関数を使用し、パラメーター変数キー変数と同じである場合、次のように使用することをお勧めします this.setState({videos});
jayeshkv

これは私のためにそれをしたものです。私はノードの初心者で、axiosモジュールのドキュメントはreactおよびsetStateと互換性がありませんでした
dabobert

20

何もバインドする必要はありません。次のようなArrow関数を使用するだけです。

class Counter extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            count: 1
        };

    }
    //ARROW FUNCTION
    delta = () => {
        this.setState({
            count: this.state.count++
        });
    }

    render() {
        return (
            <div>
                <h1>{this.state.count}</h1>
                <button onClick={this.delta}>+</button>
            </div>
        );
    }
}

それはうまくいきます違いは何ですか?なぜですか?
Ridha Rezzag

4
矢印関数を含むthisスコープは、コンテキストから継承されます。通常の関数の場合、これは常に最も近い関数を参照しますが、矢印関数の場合、この問題は取り除かれ、var that = thisをもう一度書く必要はありません。@RezzagRidha
Gabo Ruiz

1
2019年現在、これは進むべき道です(Y)
MH

6

次のものも使用できます。

<button onClick={()=>this.delta()}>+</button>

または:

<button onClick={event=>this.delta(event)}>+</button>

いくつかのパラメータを渡した場合...


JSXで矢印関数を使用することはお勧めしません
Gabe

5

これをコンストラクターにバインドする必要があり、コンストラクターの変更にはサーバーの再起動が必要であることを覚えておいてください。それ以外の場合は、同じエラーで終了します。


1
サーバーを再起動しなかったので髪を抜いていた。
kurtcorbett

5

メソッドを 'this'(デフォルトオブジェクト)にバインドする必要があります。したがって、あなたの関数がそれをコンストラクタにバインドするだけの可能性があります。

constructor(props) {
    super(props);
    this.state = { checked:false };

    this.handleChecked = this.handleChecked.bind(this);
}

handleChecked(){
    this.setState({
        checked: !(this.state.checked)
    })
}

render(){
    var msg;

    if(this.state.checked){
        msg = 'checked'
    }
    else{
        msg = 'not checked'
    }

    return (
        <div>               
            <input type='checkbox' defaultChecked = {this.state.checked} onChange = {this.handleChecked} />
            <h3>This is {msg}</h3>
        </div>
    );

4

このエラーは、さまざまな方法で解決できます。

  • ES5構文を使用している場合は、React js Documentationに従ってbindメソッドを使用する必要があります。

    上記の例では、次のようになります。

    this.delta = this.delta.bind(this)

  • ES6構文を使用している場合は、bindメソッドを使用する必要はありません。次のような方法で実行できます。

    delta=()=>{ this.setState({ count : this.state.count++ }); }


2

この問題には2つの解決策があります。

最初の解決策は、コンポーネントにコンストラクターを追加し、以下のように関数をバインドすることです。

constructor(props) {
        super(props);

        ...

        this.delta = this.delta.bind(this);
    }

これを行います:

this.delta = this.delta.bind(this); 

これの代わりに:

this.delta.bind(this);

2番目の解決策は、代わりに矢印関数を使用することです。

delta = () => {
       this.setState({
           count : this.state.count++
      });
   }

実際、矢印関数はそれ自体をバインドしませんthis。矢印は語彙的にbindそのコンテキストを機能させるため、this実際には元のコンテキストを指します

バインド機能の詳細については:

Bind関数 JavaScript Bindについて()

アロー関数の詳細については:

JavaScript ES6 —アロー関数と字句 this


1

以下で言及するように、このキーワードで新しいイベントをバインドする必要があります...

class Counter extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            count : 1
        };

        this.delta = this.delta.bind(this);
    }

    delta() {
        this.setState({
            count : this.state.count++
        });
    }

    render() {
        return (
            <div>
                <h1>{this.state.count}</h1>
                <button onClick={this.delta}>+</button>
            </div>
        );
      }
    }

1

追加

onClick = {this.delta.bind(this)}

問題を解決します。このエラーは、ES6クラスの関数を呼び出そうとしたときに発生するため、メソッドをバインドする必要があります。


1

アロー関数は、このキーワードをバインドすることを避けるためにあなたの人生をより簡単にするかもしれません。そのようです:

 delta = () => {
       this.setState({
           count : this.state.count++
      });
   }

0

この質問にはすでに解決策がありましたが、私が共有してそれを明確にしたいので、それが役立つことを願っています:

/* 
 * The root cause is method doesn't in the App's context 
 * so that it can't access other attributes of "this".
 * Below are few ways to define App's method property
 */
class App extends React.Component {
  constructor() {
     this.sayHi = 'hello';
     // create method inside constructor, context = this
     this.method = ()=> {  console.log(this.sayHi) };

     // bind method1 in constructor into context 'this'
     this.method1 = this.method.bind(this)
  }

  // method1 was defined here
  method1() {
      console.log(this.sayHi);
  }

  // create method property by arrow function. I recommend this.
  method2 = () => {
      console.log(this.sayHi);
  }
   render() {
   //....
   }
}

0
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>

    <script src="https://unpkg.com/react@0.14.8/dist/react.min.js"></script>
    <script src="https://unpkg.com/react-dom@0.14.8/dist/react-dom.min.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>

  </head>
  <body>
  <div id="root"></div>
    <script type="text/babel">

        class App extends React.Component{

            constructor(props){
                super(props);
                this.state = {
                    counter : 0,
                    isToggle: false
                }
            this.onEventHandler = this.onEventHandler.bind(this);   
            }

            increment = ()=>{
                this.setState({counter:this.state.counter + 1});
            }

            decrement= ()=>{
                if(this.state.counter > 0 ){
                this.setState({counter:this.state.counter - 1});    
                }else{
                this.setState({counter:0});             
                }
            }
            // Either do it as onEventHandler = () => {} with binding with this  // object. 
            onEventHandler(){
                this.setState({isToggle:!this.state.isToggle})
                alert('Hello');
            }


            render(){
                return(
                    <div>
                        <button onClick={this.increment}> Increment </button>
                        <button onClick={this.decrement}> Decrement </button>
                        {this.state.counter}
                        <button onClick={this.onEventHandler}> {this.state.isToggle ? 'Hi':'Ajay'} </button>

                    </div>
                    )
            }
        }
        ReactDOM.render(
        <App/>,
        document.getElementById('root'),
      );
    </script>
  </body>
  </html>

0

bindステートメントを必要なものから変更するだけです=> this.delta = this.delta.bind(this);


0
  1. 状態のチェック 、あなたが特定のプロパティを作成するかどうかをチェック状態を

this.state = {
            name: "",
            email: ""
            }
            
           
            
this.setState(() => ({ 
             comments: comments          //comments not available in state
             })) 

2. (これ)を確認します 関数内でsetStateを実行している場合(つまり、handleChange)、これにバインドする関数または関数を矢印関数にする必要があるかどうかを確認します。

##これを以下の関数にバインドする3つの方法##

//3 ways for binding this to the below function

handleNameChange(e) {  
     this.setState(() => ({ name }))
    }
    
// 1.Bind while callling function
      onChange={this.handleNameChange.bind(this)}
      
      
//2.make it as arrow function
     handleNameChange((e)=> {  
     this.setState(() => ({ name }))
     })
    
//3.Bind in constuctor 

constructor(props) {
        super(props)
        this.state = {
            name: "",
            email: ""
        }
        this.handleNameChange = this.handleNameChange.bind(this)
        }


0

ES5構文を使用している場合は、適切にバインドする必要があります

this.delta = this.delta.bind(this)

あなたは矢印の機能を使用することができますES6、あなたの上を使用している場合と、あなたは使用する必要はありません)(バインドには、

delta = () => {
    // do something
  }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.