需求:点击+1按钮,计数器+1
import React, { Component } from 'react'
export default class App extends Component {
state = {
count: 0,
}
handleClick() {
//报错: Cannot read properties of undefined (reading 'state')
console.log(this.state.count)
}
render() {
return (
<div>
<h2>计数器:{this.state.count}</h2>
<button onClick={this.handleClick}>+1</button>
</div>
)
}
}
//报错: Cannot read properties of undefined (reading 'state')
分析原因:
-
render 函数是被组件实例调用的(可以通过修改 render 函数的名字来观察到),因此 render 函数中的 this 指向当前组件实例,所以在 render 函数中通过 this 实例访问 state 和 handleClick 没有问题。
-
但!
<button onClick={this.handleClick}>+1</button>,这样写,本质上是把this.handleClick这个方法赋值给了 onClick 这个属性,当点击按钮的时候,由 React 内部直接调用 onClick,那么 this 指向就是 undefined(class 的内部,开启了局部严格模式,所以 this 不会指向 window )。
解决方法:
方法 1
高阶函数:通过 this 来直接调用 handleClick 并返回箭头函数。
柯里化:通过函数调用继续返回函数的形式,实现多次接收参数最后统一处理的函数编码形式。
export default class App extends Component {
state = {
count: 0,
}
handleClick() {
return () => {
console.log(this.state.count)
}
}
render() {
return (
<div>
<h2>计数器:{this.state.count}</h2>
<button onClick={this.handleClick()}>+1</button>
</div>
)
}
}
方法 2
包裹一层箭头函数。
箭头函数中的 this 指向“外部”,即 render 函数,而 render 函数中的 this 正是组件实例。
class App extends Component {
state = {
count: 0,
}
handleClick() {
console.log(this.state.count)
}
render() {
return (
<div>
<h2>计数器:{this.state.count}</h2>
<button onClick={() => this.handleClick()}>+1</button>
</div>
)
}
}
方法 3
使用 bind。
class App extends Component {
state = {
count: 0,
}
handleClick() {
console.log(this.state.count)
}
render() {
return (
<div>
<h2>计数器:{this.state.count}</h2>
<button onClick={this.handleClick.bind(this)}>+1</button>
</div>
)
}
}
方法 4
通过赋值语句往实例上面添加一个箭头函数。
class App extends Component {
state = {
count: 0,
}
handleClick = () => {
console.log(this.state.count)
}
render() {
return (
<div>
<h2>计数器:{this.state.count}</h2>
<button onClick={this.handleClick}>+1</button>
</div>
)
}
}
方法 5
在构造函数中再创建一个实例方法,和原型方法公用一个函数体。
class App extends React.Component {
constructor() {
super()
this.state = {
count: 0,
}
// 1. 往实例自身上又挂载了一个 handleClick 函数
// 2. 此函数的函数体是通过原型上 handleClick 函数生成的新函数
// 3. 并把原型上 handleClick 函数中的 this 通过 bind 绑定为了 this,而这里构造函数中的 this 正是实例对象
// 4. 其实点击的时候调用的是这个构造函数 handleClick(就近原则),而这个构造函数中的 handleClick 执行的是原型上的 handleClick 的函数体
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
console.log(this.state.count)
}
render() {
return (
<div>
<h2>计数器:{this.state.count}</h2>
<button onClick={this.handleClick}>+1</button>
</div>
)
}
}
本文主要讨论在React类组件中遇到的this指向问题,特别是在点击事件中导致的undefined错误。分析了问题的原因,并提供了五种解决方案:1) 使用高阶函数和柯里化;2) 包裹箭头函数;3) 利用bind;4) 通过赋值添加箭头函数;5) 在构造函数中创建实例方法。每种方法都能有效解决组件中this的指向问题。
3万+

被折叠的 条评论
为什么被折叠?



