Рубрики
Без рубрики

Вот почему нам нужно связать обработчики событий в классовых компонентах в реакции

Саурабл Мишрой Вот почему нам нужно связать обработчики событий в компонентах классов в разделе «Компоненты реакции» на ICTBACK DYKSTRA на Unsplash, изображение исходного кода, генерируемого на CANGL.Now.shile, работая над реагированием, вы должны столкнуться с контролируемыми компонентами и обработчиками событий. Нам нужно связать эти методы

Автор оригинала: FreeCodeCamp Community Member.

Саурабл Мишрой

Работая над реагированием, вы должны столкнуться с контролируемыми компонентами и обработчиками событий. Нам нужно связать эти методы к экземпляру компонента, используя .связывать () в нашем конструкторе пользовательского компонента.

class Foo extends React.Component{
  constructor( props ){
    super( props );
    this.handleClick = this.handleClick.bind(this);
  }
  
  handleClick(event){
    // your event handling logic
  }
  
  render(){
    return (
      
    );
  }
}

ReactDOM.render(
  ,
  document.getElementById("app")
);

В этой статье мы узнаем, почему нам нужно сделать это.

Я бы порекомендовал прочитать о .bind () здесь Если вы еще не знаете, что это делает.

Обвинять JavaScript, не реагировать

Ну, укладка виновата звучит немного резко. Это не то, что нам нужно сделать из-за того, как работает реагирование или из-за JSX. Это из-за того, как это Привязка работ в JavaScript.

Давайте посмотрим, что произойдет, если мы не связываем метод обработчика событий с его экземпляром компонента:

class Foo extends React.Component{
  constructor( props ){
    super( props );
  }
    
  handleClick(event){
    console.log(this); // 'this' is undefined
  }
    
  render(){
    return (
      
    );
  }
}

ReactDOM.render(
  ,
  document.getElementById("app")
);

Если вы запускаете этот код, нажмите кнопку «Нажмите« Me »и проверьте консоль. Вы увидите undefined напечатано на консоль в качестве значения это изнутри метода обработчика событий. Handleclick () Метод, кажется, есть потерял его контекст (экземпляр компонента) или это ценить.

Как «это» привязки работает в JavaScript

Как я уже говорил, это происходит из-за того, как это Привязка работ в JavaScript. Я не буду входить в много деталей в этом посте, но здесь это отличный ресурс, чтобы понять, как это Привязка работ в JavaScript.

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

Обязательное по умолчанию

function display(){
 console.log(this); // 'this' will point to the global object
}

display(); 

Это простой вызов функции. Значение это внутри Дисплей () Метод в этом случае является окном – или глобальный – объект в не строгий режим. В строгом режиме это Значение это неопределенный .

Неявное обязательство

var obj = {
 name: 'Saurabh',
 display: function(){
   console.log(this.name); // 'this' points to obj
  }
};

obj.display(); // Saurabh 

Когда мы называем функцию таким образом, – предшествует объект контекста – это Значение внутри Дисплей () установлен на obj Отказ

Но когда мы назначаем эту функцию ссылки на некоторую другую переменную и вызову функцию, используя эту новую ссылку на функцию, мы получаем другое значение это внутри Дисплей () Отказ

var name = "uh oh! global";
var outerDisplay = obj.display;
outerDisplay(); // uh oh! global

В приведенном выше примере, когда мы называем SuredisPlay () Мы не указываем объект контекста. Это простой вызов функции без объекта владельца. В этом случае значение это внутри Дисплей () вернуться к Привязка по умолчанию Отказ Это указывает на глобальный объект или undefined Если вызываемая функция использует строгий режим.

Это особенно применимо при прохождении таких функций в качестве обратных вызовов к другой пользовательской функции, сторонняя функция библиотеки или встроенная функция JavaScript, таких как Сетримс Отказ

Рассмотрим Сетримс Детное определение, как показано ниже, а затем вызовов его.

// A dummy implementation of setTimeout
function setTimeout(callback, delay){

   //wait for 'delay' milliseconds
   callback();
   
}

setTimeout( obj.display, 1000 );

Мы можем понять, что когда мы называем Сетримс JavaScript внутренне назначает obj.display к его аргументу Перезвоните .

callback = obj.display;

Это операция назначения, как мы видели раньше, вызывает Дисплей () функция, чтобы потерять свой контекст. Когда этот обратный вызов в конечном итоге вызывается внутри Сетримс , это Значение внутри Дисплей () вернуться к Привязка по умолчанию Отказ

var name = "uh oh! global";
setTimeout( obj.display, 1000 );

// uh oh! global

Явное твердое привязку

Чтобы избежать этого, мы можем Явно тяжело связываться это Значение функции с помощью Bind () метод.

var name = "uh oh! global";
obj.display = obj.display.bind(obj); 
var outerDisplay = obj.display;
outerDisplay();

// Saurabh

Теперь, когда мы называем SuredisPlay () ценность это указывает на obj внутри Дисплей () Отказ

Даже если мы пройдем obj.display Как обратный вызов, это Значение внутри Дисплей () будет правильно указать на obj Отказ

Воссоздание сценария, используя только JavaScript

В начале этой статьи мы видели это в нашем компоненте реагирования под названием Foo Отказ Если мы не связываем обработчик событий с помощью это его значение внутри обработчика событий была установлена как undefined Отказ

Как я уже говорил и объяснил, это из-за пути это Привязка работает в JavaScript и не связана с тем, как работает React. Итак, давайте удалим код AGED-CEMPORE и построить аналогичный пример чистого JavaScript для моделирования этого поведения.

class Foo {
  constructor(name){
    this.name = name
  }
  
  display(){
    console.log(this.name);
  }
}

var foo = new Foo('Saurabh');
foo.display(); // Saurabh

// The assignment operation below simulates loss of context 
// similar to passing the handler as a callback in the actual 
// React Component
var display = foo.display; 
display(); // TypeError: this is undefined

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

“Подождите минуту! Не должен это Точка значений на глобальный объект, поскольку мы выполняем это в не строгий режим в соответствии с правилами привязки по умолчанию? «Вы можете спросить.

Нет. Вот почему:

Вы можете прочитать полную статью здесь Отказ

Итак, чтобы предотвратить ошибку, нам нужно связать это Значение, как это:

class Foo {
  constructor(name){
    this.name = name
    this.display = this.display.bind(this);
  }
  
  display(){
    console.log(this.name);
  }
}

var foo = new Foo('Saurabh');
foo.display(); // Saurabh

var display = foo.display;
display(); // Saurabh

Нам не нужно делать это в конструкторе, и мы можем сделать это где-то еще. Учти это:

class Foo {
  constructor(name){
    this.name = name;
  }
  display(){
    console.log(this.name);
  }
}

var foo = new Foo('Saurabh');
foo.display = foo.display.bind(foo);
foo.display(); // Saurabh

var display = foo.display;
display(); // Saurabh

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

Почему нам не нужно связывать «это» для функций стрелки?

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

class Foo extends React.Component{
  handleClick = () => {
    console.log(this); 
  }
 
  render(){
    return (
      
    );
  }
} 

ReactDOM.render(
  ,
  document.getElementById("app")
);
class Foo extends React.Component{
 handleClick(event){
    console.log(this);
  }
 
  render(){
    return (
      
    );
  }
}

ReactDOM.render(
  ,
  document.getElementById("app")
);

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

Причина в том, что в случае функций стрелки это связан лексически Отказ Это означает, что он использует контекст окружающей функции – или глобальный – сферу, как его это ценить.

В случае примера синтаксиса полей открытых классов функция стрелки прилагается внутри Foo Функция класса или конструктора – поэтому контекст является экземпляром компонента, который мы хотим.

В случае функции стрелки в качестве примера обратного вызова функция стрелки прилагается внутри Render () Способ, который вызывается реагированием в контексте экземпляра компонента. Вот почему функция стрелки также поймает этот же контекст, а это Значение внутри он будет правильно указывать на экземпляр компонента.

Для получения более подробной информации о лексической форме это Привязка, проверьте Этот отличный ресурс Отказ

Короче говоря

В компонентах класса в реакции, Когда мы передаем функцию функции обработки событий как обратный вызов, как это

Метод обработчика событий теряет его неявно связанный контекст. Когда происходит событие, и обработчик вызывается, это Ценность возвращается в Привязка по умолчанию и установлен на undefined , в качестве деклараций классов и методы прототипа работают в строгом режиме.

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

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

Оригинал: “https://www.freecodecamp.org/news/this-is-why-we-need-to-bind-event-handlers-in-class-components-in-react-f7ea1a6f93eb/”