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
  • 11
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
这个错误通常是由于在React项目中使用了未定义的变量或方法引起的。根据引用和的描述,可能是因为在谷歌浏览器中安装了React开发工具导致的。 解决办法是修改依赖的JavaScript文件,具体步骤如下: 1. 打开项目文件夹,找到/node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ReactRefreshEntry.js文件。 2. 打开该文件,找到相关代码行。 3. 将该行代码注释掉,可以使用双斜杠(//)或者将代码行用/* */包裹起来。 4. 保存文件,并重新启动项目。 这样修改后,应该可以解决TypeError: Cannot read properties of undefined (reading 'forEach')的报错。引用中提到,换一个浏览器可能可以正常运行访问项目,这是因为其他浏览器可能没有安装React开发工具。 另外,根据引用的描述,还可能出现Error: Cannot find module 'react-dev-utils/crossSpawn'的错误。这是由于缺少相关模块导致的。可以通过安装或更新相关模块来解决这个问题。具体操作可以参考相关文档或搜索引擎上的解决方案。 总结起来,解决React启动报错TypeError: Cannot read properties of undefined (reading 'forEach')的方法包括: 1. 检查是否安装了React开发工具,如果安装了可能会导致该报错,在谷歌浏览器中可以尝试将相关代码行注释掉。 2. 检查是否缺少了某些模块,特别是引用中提到的react-dev-utils/crossSpawn模块。可以尝试安装或更新相关模块来解决问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [react 谷歌浏览器报错:Uncaught TypeError: Cannot read properties of undefined (reading ‘forEach‘)](https://blog.csdn.net/water_Popcorn/article/details/124095083)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [React启动后报错TypeError: Cannot read properties of undefined (reading ‘forEach‘)](https://blog.csdn.net/qq_40600414/article/details/121736055)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [报错记录 | Error: Cannot find module ‘react-dev-utils/crossSpawn’](https://download.csdn.net/download/weixin_38668160/14040823)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值