React - uncaught TypeError:无法读取未定义

时间:2015-08-31 18:00:07

标签: javascript reactjs

我收到以下错误

  

未捕获的TypeError:无法读取未定义的属性“setState”

甚至在构造函数中绑定delta之后。

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

18 个答案:

答案 0 :(得分:336)

这是因为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返回一个绑定函数。您需要将函数设置为其绑定值。

答案 1 :(得分:106)

ES7 + (ES2016)中,您可以使用实验function bind syntax运算符::进行绑定。这是一个语法糖,将与Davin Tryon的答案一样。

然后,您可以将this.delta = this.delta.bind(this);重写为 this.delta = ::this.delta;

对于 ES6 + (ES2015),您还可以使用ES6 + arrow function=>)来使用this

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

为什么?来自Mozilla doc:

  

在箭头函数之前,每个新函数都定义了自己的 this 值[...]。事实证明,这是一种面向对象的编程风格。

     

箭头函数捕获封闭上下文[...]

this

答案 2 :(得分:28)

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>

答案 3 :(得分:18)

在React中使用ES6代码时始终使用箭头功能,因为上下文会自动与其绑定

使用此功能:

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

代替:

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

答案 4 :(得分:12)

你不必绑定任何东西,只需使用这样的箭头函数:

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

答案 5 :(得分:6)

您也可以使用:

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

或者:

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

如果你传递了一些参数..

答案 6 :(得分:5)

您需要将其绑定到构造函数并记住对构造函数的更改需要重新启动服务器。否则,您将以相同的错误结束。

答案 7 :(得分: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>
    );

答案 8 :(得分: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>
        );
      }
    }

答案 9 :(得分:1)

添加

  

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

将解决问题。 当我们尝试调用ES6类的函数时,会出现此错误, 因此,我们需要绑定该方法。

答案 10 :(得分:1)

箭头功能可以使您的生活更加轻松,避免绑定 this 关键字。像这样:

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

答案 11 :(得分:1)

此问题有两种解决方案:

第一个解决方案是向您的组件添加一个构造函数并像下面这样绑定您的函数:

constructor(props) {
        super(props);

        ...

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

这样做:

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

代替此:

this.delta.bind(this);

第二种解决方案是改用箭头功能:

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

实际上箭头功能绑定其自己的this。箭头函数按词法bind表示其上下文,因此this实际上是指原始上下文

有关绑定功能的更多信息:

Bind function Understanding JavaScript Bind ()

有关箭头功能的更多信息:

Javascript ES6 — Arrow Functions and Lexical this

答案 12 :(得分: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>

答案 13 :(得分: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() {
   //....
   }
}

答案 14 :(得分:0)

只需更改绑定语句即可 =>     this.delta = this.delta.bind(this);

答案 15 :(得分:0)

可以通过多种方法解决此错误-

  • 如果您使用的是 ES5 语法,则按照React js Documentation 必须使用 bind 方法。

    上面的示例是这样的:

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

  • 如果使用的是 ES6 语法,则无需使用 bind 方法,则可以 用这样的东西来做:

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

答案 16 :(得分:0)

  1. 检查状态          检查状态是否创建特定属性

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

2. 选中(此)              如果您在任何函数(例如handleChange)中执行setState,请检查该函数是否绑定到此函数,或者该函数应为箭头函数。

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

答案 17 :(得分:0)

如果您使用的是ES5语法,则需要正确绑定它

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

如果您使用的是ES6及更高版本,则可以使用箭头功能,则无需使用 bind()

delta = () => {
    // do something
  }