react报错 TypeError: Cannot read property 'setState' of undefined
代码如下:
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
箭头函数最大的作用是使得this从正常情况下的动态作用域(根据运行位置确定值)变成了静态作用域(根据定义位置确定值,也就是词法作用域)。
若想了解得更详细,可以去阅读官方文档: https://reactjs.org/docs/handling-events.html
react报错 TypeError: Cannot read property 'setState' of undefined的更多相关文章
- VUE.JS 使用axios数据请求时数据绑定时 报错 TypeError: Cannot set property 'xxxx' of undefined 的解决办法
正常情况下在data里面都有做了定义 在函数里面进行赋值 这时候你运行时会发现,数据可以请求到,但是会报错 TypeError: Cannot set property 'listgroup' of ...
- Node中使用MySQL报错:TypeError: Cannot read property 'query' of undefined
Node中使用MySQL报错: TypeError: Cannot read property 'query' of undefined at /Users/sipeng/Desktop/彭思/201 ...
- 使用webpack命令打包时,报错TypeError: Cannot read property 'presetToOptions' of undefined的解决办法
我只安装了webpack,没有安装webpack-cli,第一次输入webpack打包时,提示 One CLI for webpack must be installed. These are rec ...
- vue表单校验提交报错TypeError: Cannot read property 'validate' of undefined
TypeError: Cannot read property 'validate' of undefined at VueComponent.submitForm (plat_users.html: ...
- vue报错TypeError: Cannot read property 'protocol' of undefined
错误信息如下所示: isURLSameOrigin.js?3934:57 Uncaught (in promise) TypeError: Cannot read property 'protocol ...
- vue报错TypeError: Cannot read property '$createElement' of undefined
报错截图: 这个错误就是路由上的component写成了components
- Node.js报错TypeError: Cannot read property 'isDirectory' of undefined
截图如下: 原因如下:记住"./uploads" 后要加一个/ fs.stat("./uploads/" + files[i], function(err, s ...
- VUE - 使用axios数据请求时数据绑定时 报错 TypeError: Cannot set property 'xxxx' of undefined 的解决办法
created() { var that=this axios.get('http://jsonplaceholder.typicode.com/todos') .then( ...
- JS报错:Cannot read property 'type' of undefined
在做图片上传功能的时候,遇到了JS无法识别图片type的问题,在使用过程中是没有问题的,但是不知道为什么浏览器的Console报这个错误: Uncaught TypeError: Cannot rea ...
随机推荐
- web前台界面的两种验证方式
JSON的全称是"JavaScript Object Notation",意思是JavaScript对象表示法,它是一种基于文本,独立于语言的轻量级数据交换格式. 第一种: 用户体 ...
- centos7安装手册
一:centos7下载 下载centos可以访问阿里云完成centos 7.7下载(建议使用迅雷下载):http://mirrors.aliyun.com/centos/7.9.2009/isos/x ...
- Refit集成consul在asp.net core中的实践
前言 github:https://github.com/alphayu/ Refit.WebApiClient.Feign等都是支持声名式的Restful服务调用的开源组件. 这个几个组件都综合研究 ...
- Redis-基础和应用篇
2020,到新公司这一年多以来,更新文章和总结知识的习惯被丢掉了.我复盘了下自己,原因不是公司技术氛围不好,也不是每天业务需求太多,其根本原因还是---惰性.作为我们技术人随着年龄的增长,精力也会被生 ...
- .NET Core 中的日志与分布式链路追踪
目录 .NET Core 中的日志与分布式链路追踪 .NET Core 中的日志 控制台输出 非侵入式日志 Microsoft.Extensions.Logging ILoggerFactory IL ...
- Lesson_strange_words3
can 电话耳机,(头戴式听筒) determine 决定 perform 执行 regular 常规的 duty 责任 compatible 兼容 preset 预置,预设 in either or ...
- 从零开始的C程序设计大作业——学生成绩管理系统
前言 学生成绩管理系统可以说是C语言程序设计的结课的必备大作业了.花了些时间,费了些头发肝了下,完成了两个系统,一个是控制台版本的,另一个用easyx图形库进行了优化. 先放出完成后的演示图片占个坑. ...
- thinkphp3.2框架运行原理
thinkphp3.2是使用率非常普遍的国产php框架,以简单易于上手闻名,那么它框架结构是怎样的? tp3.2设计简单来说就是CBD,core(框架核心文件),bebavior(行为,tp3.2一大 ...
- CentOS7上安装jdk,mysql
最近笔者的云服务器由于中毒,重装系统了... 所以就记录下所有服务的搭建过程吧 1.安装jdk 在oracle上下载linux系统的jdk,笔者这里使用的是1.8 https://www.oracle ...
- new ArrayList(0) 和 new ArrayList() 和一样吗?
第一感觉是一样的,盲猜后者调用了前者,并传入参数 0.然而,无论是 JDK 7 还是 JDK 8,这两个方法构造的结果都是不一样的.JDK 开发人员在这方面作了优化. JDK 7 在 Java 7 中 ...