SetInterval и обратный вызов со стрелочными функциями в React

У меня есть компонент React, который использует setInterval. Я хочу иметь возможность использовать компонент this внутри setInterval, но this становится окном внутри setInterval, а затем this становится undefined в обратном вызове.

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

Вот пример:

class MyComponent extends React.Component {
  constructor(){
    super()
    this.hasEndedTimer = this.hasEndedTimer.bind(this)
    ...
    this.hasEndedTimer(()=>{
      // the callback 'this' is now undefined? Even though an arrow 
      function?    
    })      
  }
...
  hasEndedTimer(callback) {
    const intervalId = setInterval(() => {
      // 'this' is now the window instead of the component? Even though arrow
      if (somecondition()) callback()
    }, 1000)
  }

...
}

Могу ли я поддерживать контекст this компонента реакции внутри setInterval?

ПРИМЕЧАНИЕ. Если я изменю стрелочную функцию в setInterval на анонимную функцию, к которой я привязываю this, контекст this останется компонентом.

  hasEndedTimer(callback) {
    const intervalId = setInterval((function() {
      // 'this' is now the component. Works as expected.
      if (somecondition()) callback()
    }).bind(this), 1000)
  }

Также constructor должен принять props в качестве аргумента и передать его super(). А чтобы привязать функции к вашему экземпляру класса, вы должны либо объявить его в конструкторе с помощью this.myFunction =, либо в области действия класса с синтаксисом свойства класса. Вы могли это перепутать.

trixn 02.11.2018 15:56

Извините, да, это был просто мой сокращенный синтаксис, чтобы показать пример. Это действительно происходит в коде. Я обновил выше, чтобы отразить. Я не верю, что реквизит требуется в конструкторе, если вы не передаете его в super.

user3331142 02.11.2018 19:00

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

trixn 02.11.2018 19:02

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

user3331142 02.11.2018 19:05
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
4
1 727
1

Ответы 1

Надеюсь, что это поможет вам.

Конструктор должен иметь super ().

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

И вам нужно привязать hasEndedTimer в конструкторе.

Если вы забудете привязать this.handleClick и передать его, это будет неопределенным при фактическом вызове функции.

this.hasEndedTimer = this.hasEndedTimer.bind(this)

А при использовании стрелочной функции связывать (this) не нужно.

Об этом в setInterval все по-другому.

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

declare (){
  console.info(...);
};
setInterval(this.declare.bind(this), 1000);

Итак, функция, которую вы устанавливаете внутри setInterval, на самом деле является функцией обратного вызова и может указывать на экземпляр класса. Таким образом, «this» работает хорошо.

О стрелочной функции.

Сама стрелочная функция не имеет этого, она должна наследовать от верхней части цепочки области видимости. И нет необходимости использовать привязку. В способах определения стрелочной функции this.hasEndedTime что-то не так.

this.hasEndedTimer = ()=>{
   ...  
}
//how to use it 
this.hasEndedTimer()

И setInterval в стрелочной функции должен обращать внимание на «this» внутри функции.

«Эта» внутренняя функция является фиксированной и указывает на определенную область, которая не используется. Вот пример.

function Timer() {
  this.s1 = 0;
  setInterval(() => this.s1++, 1000);
}
var timer = new Timer();
setTimeout(() => console.info('s1: ', timer.s1), 3100);

Что касается конструктора, требующего привязки super и hasEnded в конструкторе, я просто оставил это в спешке, чтобы получить пример. Я обновил свой вопрос. Думаю, я до сих пор не понимаю, почему здесь не работает стрелочная функция вместо экземпляра класса?

user3331142 02.11.2018 19:03

@ user3331142 Я добавил кое-что о стрелочной функции.

Root 03.11.2018 07:15

Другие вопросы по теме