Почему и когда нам нужно связывать функции и eventHandlers в 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}>

Как разные версии? Или это просто вопрос предпочтения?


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

Ответ 1

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

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

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

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

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

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

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

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

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

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

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

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

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

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

б. Вы можете использовать .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}>

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

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

Ответ 2

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

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

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

Существует три способа привязки вашей функции onChange к правильному контексту

Первая

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

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

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, используя функцию Arrow

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

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

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

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


return <input onChange={this.someEventHandler}>

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