[英]Javascript class instance method does not work with onClick callback event in react
當單擊我的頁面上的按鈕時,我試圖更新我的狀態變量。 但是我發現我不能使用 react 類組件方法。 這是最小的可重現示例。
import React, { Component } from 'react'
export class Name extends Component {
constructor(){
super();
this.state = {
name : "Farhan Ahmed"
}
}
clickMe() {
this.setState({
name:"Ahmed Farhan"
})
}
render() {
return (
<div>
<h1>{this.state.name}</h1>
<button className="btn btn-success" onClick={this.clickMe}>Change Text</button>
</div>
)
}
}
export default Name
錯誤 :
TypeError: Cannot read properties of undefined (reading 'setState')
但是當我用箭頭函數替換它時,它對我有用。
我的問題是為什么在這種情況下常規類方法不起作用,為什么我需要用箭頭函數替換它?
在此處找到的文檔https://reactjs.org/docs/handling-events.html中解釋了此錯誤以及可能的解決方案。 如果您沒有使用文檔中提到的實驗性“公共類字段語法”,您可以bind
您的函數,或者使用箭頭函數:
帶綁定
onClick={this.clickMe.bind(this)}
箭頭函數
onClick={() => this.clickMe()}
這些是最常見的(我個人見過),但文檔也提供了更多的解決方案。
按鈕沒有被點擊,但函數會在組件渲染時運行。
onClick={this.clickMe}
和這個;
onClick={() => this.clickMe}
功能僅在單擊按鈕時起作用。
這個問題不是特定於反應的,而是實際上與 Javascript 的一般工作方式有關。
this
在 javascript 中的功能略有不同。 由於 React 是一個 javascript 庫, this
React 中的this
遵循相同的概念。
在 javascript 中, this
關鍵字的行為基於函數的調用方式。 this
在 javascript 中保存對當前執行上下文的引用。 根據函數的調用方式, this 可以引用不同的對象。
如果使用像obj.functionName()
這樣的對象調用函數,那么這將始終返回對對象的引用
如果一個函數像functionName()
這樣的獨立函數被調用,那么這將返回對 window 對象的引用,但如果啟用了嚴格模式,那么這將返回 undefined。
如果函數是從回調中調用的類方法,例如callback = obj.functionName(); callback();
callback = obj.functionName(); callback();
那么這將返回未定義。
現在我們更感興趣的是了解我們將類函數設置為回調onClick
的第三點。
讓我們通過一個例子來理解它
考慮具有以下方法的類 Rectangle
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
// Getter
area() {
console.log(this);
return this.calcArea();
}
// Method
calcArea() {
return this.height * this.width;
}
}
現在當我們這樣做時
const square = new Rectangle(10, 10);
square.area()
它給了我們預期的結果
Rectangle {height: 10, width: 10} /* value of this */
100
現在,當我們將相同的內容存儲在回調中並調用回調函數時
callback = square.area;
callback()
這給了我們錯誤:
undefined /* value of this */
VM106:9 Uncaught TypeError: Cannot read properties of undefined (reading 'calcArea')
at area (<anonymous>:9:17)
at <anonymous>:1:1
如您所見, this 的值未定義。 這是因為 area 方法被重新定義了范圍並最終丟失了它的上下文,即它的this
關鍵字引用。 你的情況也發生了同樣的事情。
解決方案 :
現在嘗試使用箭頭函數或將相同的函數綁定到類,您將能夠成功調用回調。
使用箭頭函數
area = () => {
console.log(this.width, this.height);
return this.calcArea();
}
使用箭頭函數的優點是它不會重新定義“this”關鍵字的范圍,從而無需在構造函數中綁定“this”
通過在構造函數中綁定函數
constructor(height, width) {
this.height = height;
this.width = width;
this.area = this.area.bind(this);
}
現在使用回調調用相同的
const square = new Rectangle(10, 10);
callback = square.area;
callback()
會給我們結果
Rectangle {height: 10, width: 10, area: ƒ}
100
這是綁定事件處理程序的好方法,但為每個事件處理程序重復相同的一組步驟將是一項繁忙的任務。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.