react报错 TypeError: Cannot read property 'setState&am
代码如下: class test extends Component { constructor(props) { super(props); this.state = { liked: false }; } handleClick(event) { this.setState({liked: !this.state.liked}); } render() { var text = this.state.liked ? '喜欢' : '不喜欢'; return ( <div onClick={this.handleClick}> 你<b>{text}</b>我。点我切换状态。 </div> ); } } export default test; 可以正常展示页面: 但是按钮一按就会报错。 为什么会出现这种情况呢? 因为点击按钮时,到了handleClick()方法中的this已经不是组件里的this了。 第一种解决方法是:手动绑定this。将 constructor(props) { super(props); this.state = { liked: false }; } 改为 constructor(props) { super(props); this.state = { liked: false }; this.handleClick = this.handleClick.bind(this);//手动绑定 }第二种解决办法是:将 handleClick(event) { this.setState({liked: !this.state.liked}); }改为 handleClick= (e) => { this.setState({liked: !this.state.liked}); } 这种解决方法之所以能解决问题,就引申到了另外一个问题:函数作为React组件的方法时,箭头函数和普通函数的区别是什么? 举个例子:下面2个a的定义有什么区别? class App extends Component { a() { console.log(1) } a = () => { console.log(1) } } 第一个 a 不必说,是原型方法的定义。宽松模式下对应 ES5 就是 App.prototype.a = function() {}
第二个是 Stage 2 Public Class Fields 里面的写法,babel 下需要用 Class properties transform Plugin 进行转义。相当于: class App extends Component {
constructor (...args) {
super(...args)
this.a = () => {
console.log(1)
}
}
}
为什么需要第二种写法? 在 React 里面,要将类的原型方法通过 props 传给子组件,传统写法需要 bind(this),否则方法执行时 this 会找不到: <button onClick={this.handleClick.bind(this)}></button>
或者 <button onClick={(e) => this.handleClick(e)}></button>
这种写法难看不说,还会对 React 组件的 shouldComponentUpdate 优化造成影响。 这是因为 React 提供了 shouldComponentUpdate 让开发者能够控制避免不必要的 render,还提供了在 shouldComponentUpdate 自动进行 Shallow Compare 的 React.PureComponent,继承自 PureComponent 的组件只要 props 和 state 中的值不变,组件就不会重新 render。 然而如果用了 bind this,每次父组件渲染,传给子组件的 props.onClick 都会变,PureComponent 的 Shallow Compare 基本上就失效了,除非你手动实现 shouldComponentUpdate. 使用 Public Class Fields 的这种写法,就解决了这个问题。另外还有其他若干种办法,比如先定义原型方法,然后在 constructor 里面 bind 一遍;或者使用 decorator 进行 bind 等: class A {
constructor() {
this.a = this.a.bind(this)
}
a() {}
// or
@bindthis
b() {}
}
而箭头函数除了代码少。与普通函数最大的不同就是:this是由声明该函数时候定义的,一般是隐性定义为声明该函数时的作用域this。 var a = ()=>{
console.log(this)
}
//等同于
var a = function(){
console.log(this)
}.bind(this);
a(); //Window
var b = function(){
console.log(this)
};
b(); //Window
var obj = { a,b };
obj.a(); //Window
obj.b(); //obj
若想了解得更详细,可以去阅读官方文档: https://reactjs.org/docs/handling-events.html (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |