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 ...
随机推荐
- 修改/查看ssh端口
修改ssh端口 vi /etc/ssh/sshd_config 将Port修改为需要的端口 Port 212 重启ssh服务 service sshd restart 查看ssh端口 netstat ...
- git 知识点积累
1.初始化指定目录作为git目录 git init newpro 2.git add xx.uve 3.克隆项目 git clone git clone git://github.com/schac ...
- java之volatile
一.谈谈对volatile的理解 volatile是java虚拟机提供的轻量级的同步机制 保证可见性.不保证原子性.禁止指令重排 1.可见性理解:所有线程存放都是主内存的副本(比如某个变量值为25), ...
- hbase:ERROR: org.apache.hadoop.hbase.ipc.ServerNotRunningYetException: Server is not running yet
hbase连接deug:DEBUG [main-SendThread(bigdata.server1:2181)] - Reading reply sessionid:0x16f764e7f6e000 ...
- linux系统修改不成功无法修改密码
一.问题描述 新上架的浪潮服务器使用装机平台进行统一安装,安装完成后修改用户密码时统一无法修改,使用root账户无法修改其他用户密码,自身根密码也无法修改成功,报错如下 Changing passwo ...
- linux下网络设置和远程连接
配置ip.子网掩码.静态设置.开机启动ONBOOT网卡 /etc/sysconfig/network-scripts/ifcfg-eth0 重启网络 service network restart ...
- 利用python 5分钟制作一款小游戏
1.安装pygame 在命令行cmd中输入:pip install pygame ( 注:如果安装不成功,需要输入:python -m pip install --user --upgrade pip ...
- Cocos Creator 新资源管理系统剖析
目录 1.资源与构建 1.1 creator资源文件基础 1.2 资源构建 1.2.1 图片.图集.自动图集 1.2.2 Prefab与场景 1.2.3 资源文件合并规则 2. 理解与使用 Asset ...
- exchangeNetwork
泛洪(Flooding) 转发(Forwarding) 丢弃(Discarding) 交换机中有一个MAC地址表,里面存放了MAC地址与交换机的映射关系.MAC地址表也称为CAM(Content Ad ...
- 为什么 StringBuffer 有 toStringCache 而 StringBuilder 没有?
对于 StringBuilder 和 StringBuffer 的源码会发现,StringBuffer 中有一个叫 toStringCache 的成员变量,用来缓存 toString() 方法返回字符 ...