Зачем и когда нам нужно связывать функции и обработчики событий в React?

class SomeClass extends Component{
  someEventHandler(event){
  }
  render(){
    return <input onChange={------here------}>
  }
}

Я вижу разные версии ------here------ части.

// 1
return <input onChange={this.someEventHandler.bind(this)}>

// 2
return <input onChange={(event) => { this.someEventHandler(event) }>

// 3
return <input onChange={this.someEventHandler}>

Чем отличаются версии? Или это просто вопрос предпочтений?


Спасибо всем за ответы и комментарии. Все они полезны, и я настоятельно рекомендую прочитать эту ссылку ПЕРВЫМ, если вы, как и я, запутались в этом.
http://blog.andrewray.me/react-es6-autobinding-and-createclass/


person kukrt    schedule 13.12.2016    source источник
comment
предложил прочитать blog.andrewray.me/react-es6-autobinding-and-createclass   -  person Andy Ray    schedule 13.12.2016
comment
Вы знаете, что делает .bind и как работает this?   -  person Felix Kling    schedule 13.12.2016
comment
Существует также предлагаемый оператор привязки ::. Используйте так: return <input onChange={::this.someEventHandler} /> с подходящим преобразованием Babel.   -  person neezer    schedule 13.12.2016
comment
gist.github.com/fongandrew/f28245920a41788e084d77877e65f22f рекомендуется прочитать   -  person Anupama Karunarathna    schedule 08.07.2020


Ответы (2)


Связывание — это не то, что специфично для React, а то, как this работает в Javascript. Каждая функция/блок имеет свой собственный контекст, для функций он более специфичен в зависимости от того, как он вызывается. Команда React приняла решение, что this не будет привязан к пользовательским методам класса (то есть не к встроенным методам, таким как componentDidMount), при добавлении поддержки ES6 (синтаксис класса).

Когда вы должны связать контекст, зависит от цели функции, если вам нужно получить доступ к свойствам, состоянию или другим членам класса, вам нужно будет связать его.

В вашем примере каждый из них отличается, и это зависит от того, как настроен ваш компонент.

Предварительная привязка к вашему классу

.bind(this) используется для привязки этого контекста к вашей функции компонентов. Однако он возвращает новую ссылку на функцию каждый цикл рендеринга! Если вы не хотите привязываться к каждому использованию функции (например, в обработчике кликов), вы можете предварительно привязать функцию.

a. в вашем конструкторе выполните привязку. он же

class SomeClass extends Component{
    constructor(){
        super();
        this.someEventHandler = this.someEventHandler.bind(this);
    }
    someEventHandler(event){
    }
    ....
} 

b. создайте свои пользовательские функции на функциях жирных стрелок класса. он же

class SomeClass extends Component{
    someEventHandler = (event) => {
    }
    ....
}

Привязка времени выполнения к вашему классу

несколько распространенных способов сделать это

а. вы можете обернуть функцию обработчика компонентов встроенной лямбда-функцией (жирная стрелка).

onChange={ (event) => this.someEventHandler(event) }

это может обеспечить дополнительную функциональность, например, если вам нужно передать дополнительные данные для обработчика кликов <input onChange={(event) => { this.someEventHandler(event, 'username') }>. То же самое можно сделать с bind

b. вы можете использовать .bind(this), как описано выше.

onChange={ this.someEventHandler.bind(this) }

с дополнительными параметрами <input onChange={ this.someEventHandler.bind(this, 'username') }>

Если вы хотите избежать создания новой ссылки на функцию, но вам все же нужно передать параметр, лучше всего абстрагировать его дочернему компоненту. Подробнее об этом можно прочитать здесь

В ваших примерах

// 1
return <input onChange={this.someEventHandler.bind(this)}>

Это просто привязка обработчика событий времени выполнения к вашему классу.

// 2
return <input onChange={(event) => this.someEventHandler(event) }>

Другая среда выполнения привязывается к вашему классу.

// 3
return <input onChange={this.someEventHandler}>

Вы просто передаете функцию в качестве функции обратного вызова, которая срабатывает, когда происходит событие щелчка, без дополнительных параметров. Обязательно предварительно привяжите!

Подвести итоги. Хорошо подумать о том, как оптимизировать ваш код, у каждого метода есть полезность/цель в зависимости от того, что вам нужно.

person John Ruddell    schedule 13.12.2016

Зачем привязывать функцию React?

Когда вы определяете компонент с помощью класса ES6, общий шаблон заключается в том, что обработчик событий является методом класса. В JavaScript методы класса не связаны по умолчанию. Если вы забудете bind this.someEventHandler и передадите его onChange, это будет неопределенным при фактическом вызове функции.

Как правило, если вы ссылаетесь на метод без () после него, например onChange={this.someEventHandler}, вы должны привязать этот метод.

Есть три способа привязать вашу функцию onChange к правильному контексту.

Первый

return <input onChange={this.someEventHandler.bind(this)}>

В этом случае мы используем bind явно, чтобы сделать событие onChange доступным в качестве аргумента для обработчика событий. Мы также можем отправить какой-либо другой параметр с типом синтаксиса, например

return <input onChange={this.someEventHandler.bind(this, state.value)}>

Второй

return <input onChange={(event) => { this.someEventHandler(event) }>

Это синтаксис ES6, с помощью которого мы можем указать параметры, которые мы хотим передать функции someEventHandler. Однако это эквивалентно .bind(this). Это также дает нам возможность отправлять другие атрибуты вместе с событием, например

return <input onChange={(event, value) => { this.someEventHandler(event, value) }>

Третий

Определите функцию someEventHandler, используя функцию стрелки

someEventHandler = () => {
    console.log(this); // now this refers to context of React component
}

arrow function не имеет собственного this, используется значение this окружающего контекста выполнения, и, следовательно, вышеуказанная функция получает правильный контекст.

или привяжите его в конструкторе, например

constructor(props) {
   super(props);
   this.someEventHandler = this.someEventHandler.bind(this);
}


return <input onChange={this.someEventHandler}>

В этом методе событие напрямую связано с функцией someEventHandler. Никакие другие параметры не могут быть переданы таким образом

person Shubham Khatri    schedule 13.12.2016
comment
@JohnRuddell Я не понял твоей точки зрения. Может быть, я что-то пропустил. Не могли бы вы немного объяснить - person Shubham Khatri; 13.12.2016
comment
Хорошо, да, так что в основном .bind(this) передает только контекст и не имеет ничего общего с переданными аргументами. Например, если бы я сделал это onClick={this.someEventHandler.bind(this)}, то функция-обработчик передала бы ей мой контекст (также известный как this), но также событие было бы передано ей в качестве первого аргумента. так что... someEventHandler(event) { console.log(event) } будет событием щелчка на элементе ввода. .bind(this) просто делает так, что в этой функции ваш this контекст является контекстом класса - person John Ruddell; 13.12.2016
comment
@ShubhamKhatri Что вы имеете в виду, когда говорите, что в JavaScript методы класса по умолчанию не связаны? - person human; 14.07.2019