React - uncaught TypeError: Cannot read property 'setState' of undefined
我收到以下错误
Uncaught TypeError: Cannot read property 'setState' of undefined
甚至在构造函数中绑定delta之后。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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 ( {this.state.count} <button onClick={this.delta}>+</button> ); } } |
这是由于
为了在构造函数中绑定set
1 2 3 4 5 6 7 8 9 | constructor(props) { super(props); this.state = { count : 1 }; this.delta = this.delta.bind(this); } |
目前,您正在调用bind。但是bind返回一个绑定函数。您需要将函数设置为其绑定值。
在ES7 +(ES2016)中,您可以使用实验函数绑定语法operator
然后,您可以将
对于ES6 +(ES2015),您还可以使用ES6 +箭头功能(
1 2 3 4 5 | delta = () => { this.setState({ count : this.state.count + 1 }); } |
为什么?来自Mozilla文档:
Until arrow functions, every new function defined its own this value [...]. This proved to be annoying with an object-oriented style of programming.
Arrow functions capture the this value of the enclosing context [...]
ES5和ES6课程之间存在差异。因此,实现之间也会有一点差异。
这是ES5版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | var Counter = React.createClass({ getInitialState: function() { return { count : 1 }; }, delta: function() { this.setState({ count : this.state.count++ }); }, render: function() { return ( {this.state.count} <button onClick={this.delta}>+</button> ); } }); |
这是ES6版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class Counter extends React.Component { constructor(props) { super(props); this.state = { count : 1 }; } delta() { this.setState({ count : this.state.count++ }); } render() { return ( {this.state.count} <button onClick={this.delta.bind(this)}>+</button> ); } } |
请注意,除了类实现中的语法差异之外,事件处理程序绑定存在差异。
在ES5版本中,它是
1 | <button onClick={this.delta}>+</button> |
在ES6版本中,它是:
1 | <button onClick={this.delta.bind(this)}>+</button> |
在React中使用ES6代码时,始终使用箭头函数,因为此上下文会自动与其绑定
用这个:
1 2 3 4 | (videos) => { this.setState({ videos: videos }); console.log(this.state.videos); }; |
代替:
1 2 3 4 | function(videos) { this.setState({ videos: videos }); console.log(this.state.videos); }; |
你不必绑定任何东西,只需使用这样的箭头函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | class Counter extends React.Component { constructor(props) { super(props); this.state = { count: 1 }; } //ARROW FUNCTION delta = () => { this.setState({ count: this.state.count++ }); } render() { return ( {this.state.count} <button onClick={this.delta}>+</button> ); } } |
您还可以使用:
1 | <button onClick={()=>this.delta()}>+</button> |
要么:
1 | <button onClick={event=>this.delta(event)}>+</button> |
如果你传递一些参数..
您需要将其绑定到构造函数并记住对构造函数的更改需要重新启动服务器。否则,您将以相同的错误结束。
您必须使用'this'(默认对象)绑定方法。
所以无论你的函数是什么,只需在构造函数中绑定它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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 ( <input type='checkbox' defaultChecked = {this.state.checked} onChange = {this.handleChecked} /> This is {msg} ); |
这个错误可以通过各种方法解决 -
-
如果您使用的是ES5语法,那么根据React js Documentation,您可以使用它
必须使用绑定方法。对于上面的例子,这样的事情:
this.delta = this.delta.bind(this) -
如果您使用的是ES6语法,那么您无需使用bind方法
做这样的事情:delta=()=>{
this.setState({
count : this.state.count++
});
}
您必须使用此关键字绑定新事件,如下所述...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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 ( {this.state.count} <button onClick={this.delta}>+</button> ); } } |
添加
onClick={this.delta.bind(this)}
将解决问题。
当我们尝试调用ES6类的函数时会出现此错误,
所以我们需要绑定方法。
这个问题有两个解决方案:
第一个解决方案是在组件中添加构造函数并将函数绑定为如下:
1 2 3 4 5 6 7 | constructor(props) { super(props); ... this.delta = this.delta.bind(this); } |
这样做:
1 | this.delta = this.delta.bind(this); |
而不是这个:
1 | this.delta.bind(this); |
第二种解决方案是使用箭头功能:
1 2 3 4 5 | delta = () => { this.setState({ count : this.state.count++ }); } |
实际上箭头功能不会绑定它自己的
有关绑定功能的更多信息:
绑定功能
理解JavaScript绑定()
有关箭头功能的更多信息:
Javascript ES6 - 箭头函数和词法
只需从您拥有的内容中更改绑定语句即可
=>
this.delta = this.delta.bind(this);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> Hello World <script src="https://unpkg.com/[email protected]/dist/react.min.js"> <script src="https://unpkg.com/[email protected]/dist/react-dom.min.js"> <script src="https://unpkg.com/[email protected]/babel.min.js"> </head> <body> <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( <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> ) } } ReactDOM.render( <App/>, document.getElementById('root'), ); </body> </html> |
虽然这个问题已经有了解决方案,但我只想分享我的解决方案,希望它有所帮助:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | /* * 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() { //.... } } |
检查状态是否创建特定属性
1 2 3 4 5 6 7 8 9 10 | this.state = { name:"", email:"" } this.setState(() => ({ comments: comments //comments not available in state })) |
2.检查(这)
如果在任何函数内部执行setState(即handleChange),请检查函数是否绑定到此函数或函数应该是箭头函数。
## 3种方法将此绑定到下面的函数##
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | //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) } |
箭头功能可以让您的生活更轻松,以避免绑定此关键字。像这样:
1 2 3 4 5 | delta = () => { this.setState({ count : this.state.count++ }); } |