Какой объект владеет кодом обработчика реагирования на клики? - PullRequest
1 голос
/ 06 июля 2019

Я знаю, что при использовании методов класса 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 ]

1 голос
/ 06 июля 2019

Это зависит от того, как вы вызываете функцию, и от того, связываете вы ее или нет.

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.

1 голос
/ 06 июля 2019

Ваше «this» будет «неопределенным», потому что React вызывает вашу функцию за кулисами, и он doesn't вызывает ее из экземпляра объекта (IE MyComponent.onClickHandler(e)), он вызывает ее так: (onClickHandler(e))

Упрощенная модель того, что происходит без участия React, выглядит примерно так .....

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)
)

Метод, позволяющий обойти это, состоит в том, чтобы связать "this" функции в конструкторе компонента IE

constructor(props: IProps) {
     super(props);
     this.onClickHandler = this.onClickHandler.bind(this);
}

На самом деле это «лучший метод» определения всех функций в пределах class для компонентов React, поскольку функции стрелок не идут в прототипе классов, и, следовательно, свежие функции создаются для каждого новогоРеагировать на экземпляр этого компонента;однако с функциями, не являющимися стрелками, каждый экземпляр работает с прототипом и, следовательно, повторно используется для каждого экземпляра компонента реакции.

Трюки, такие как autobind, также не являются оптимальной практикой, поскольку привязка this каждой функции не требуется, поскольку только функции, вызываемыеДля реагирования необходимо, чтобы их this были связаны и 99% времени использовались только как функции, используемые в качестве обработчиков событий.

...