簡體   English   中英

Javascript 類實例方法不適用於反應中的 onClick 回調事件

[英]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()}

這些是最常見的(我個人見過),但文檔也提供了更多的解決方案。

當您嘗試在不綁定函數的情況下訪問this關鍵字時, this關鍵字未定義。 因此,您需要在構造函數中綁定該函數,或者使用箭頭函數語法來確保this綁定在該函數中。 您可以查看綁定方法方法和箭頭函數的文檔

按鈕沒有被點擊,但函數會在組件渲染時運行。

onClick={this.clickMe}  

和這個;

onClick={() => this.clickMe} 

功能僅在單擊按鈕時起作用。

閱讀: https : //beta.reactjs.org/learn/responding-to-events

這個問題不是特定於反應的,而是實際上與 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM