哪个对象拥有反应点击处理程序代码?

时间:2019-07-06 00:07:34

标签: reactjs typescript onclick this

我知道在使用React类方法时,箭头函数是锁定this的好方法。例如,我可能有一个点击处理程序:

clickHandler = () => {
    // some code using 'this'
    // eg this.state
}

// ... and in the render method
<button onClick={() => this.clickHandler()}>Test Button</button>

但是,如果我要使用非箭头函数语法,则哪个对象拥有代码?也就是说,this是什么?

我尝试了以下操作,但Typescript无法编译:

clickHandler = function() {
    console.log(this);   // also tried to coerce this as any type  
}

// Error: 'this' implicitly has type 'any' because it does not have a type annotation.ts(2683)

2 个答案:

答案 0 :(得分:1)

您的“ this”将为“ undefined”,因为React在后台调用了您的函数,并且doesn't从对象实例(IE MyComponent.onClickHandler(e))调用了它,就像这样{{1} }

在没有React参与的情况下发生的事情的简化模型看起来像这样.....

(onClickHandler(e))

用于解决此问题的方法是将函数的“ this”绑定到组件I.E的构造函数中。

class FakeReactComponent {
  myName() {
     console.log(this);
  }
}
// this is what you give a onClick prop on an element.
const functionPassedToOnClick= new FakeReactComponent().myName;

console.log(
  functionPassedToOnClick() // this is how react calls it (this is undefined)
)

实际上,这是在constructor(props: IProps) { super(props); this.onClickHandler = this.onClickHandler.bind(this); } 中为React Components定义所有函数的“最佳实践”方法,因为箭头函数没有出现在类原型上,因此将为该函数的每个新React实例创建新函数。零件;但是,使用非箭头功能时,每个实例都在原型上,因此可以为每个React组件实例重复使用。

像autobind这样的技巧也不是最佳实践,因为绑定每个函数的class是不必要的,因为只有React调用的函数需要绑定this,并且有99%的时间是唯一的函数作为事件处理程序。

答案 1 :(得分:1)

这取决于您如何调用函数以及是否绑定它。

class Test extends React.Component {
    clickHandler = function() {
        console.log(this);
    }

    render() {
        return (
            <div>
                <button onClick={this.clickHandler}>Option A</button>
                <button onClick={this.clickHandler.bind(this)}>Option B</button>
                <button onClick={() => this.clickHandler()}>Option C</button>
            </div>
        );
    }
}

通过Option A按钮,点击处理程序将直接传递到<button />元素。由于React假设您绑定了this并且不会为您这样做,所以this中的clickHandler将是undefined

使用Option B按钮将this.clickHandler明确绑定到this,在这种情况下,this中的clickHandler将引用该特定实例Test组件。

对于Option C(这是您在做的问题),我们没有将this.clickHandler设置为onClick处理程序,但是我们正在定义新箭头调用 this.clickHandler的功能。在这种情况下,新箭头功能将自动将Test组件获取为this,并将其传递到clickHandler

请注意,Option A版本将允许组件显式绑定处理程序:

class Button extends React.Component {
    render() {
        return (
            <button
                onClick={this.props.onClick.bind(this)}
                children={this.props.children}
            />
        );
    }
}

class Test extends React.Component {
    clickHandler = function() {
        console.log(this);
    }

    render() {
        return <Button onClick={this.clickHandler}>Click</Button>;
    }
}

在这种情况下,this中的Test.clickHandler()实际上是对Button实例的引用。