ReactJS: Uncaught (в обещании) this.setState не является функцией - PullRequest
0 голосов
/ 03 июля 2018

Я имею дело со следующей ошибкой:

Home.js: 231 Uncaught (в обещании) TypeError: _this9.setState не является функцией. Ошибка исходит из последней строки следующей функции:

checkIfRunning() {
  return fetch('/api/following/iscurrentlyrunning', {
    credentials: 'include',
  })
    .then(response => {
      console.log(response.status);
      if (response.status === 200) {
        return response.json();
      }
    })
    .then(response => {
      let cState = this.state;
      cState.running = response;
      this.setState(cState);
    });
}

Я связал функцию в конструкторе компонентов, и когда я вызываю ее отдельно, она работает нормально. Проблема возникает, когда я пытаюсь вызвать функцию в таймере (setInterval). В componentWillMount я вызываю несколько функций:

componentWillMount() {
  this.checkIfFirstTimeLogin()
    .then(() => {
      // user already exists
      if (!this.state.firstLogin) {
        this.Name();
        this.getRole();
        setInterval(() => this.checkIfRunning(), 10000);
      }
    })
    .then(() => {
      let cState = this.state;
      cState.pageLoading = false;
      this.setState(cState);
    })
    .catch(error => console.log(error));
}

У меня есть интуиция, что цепь обещаний нарушает связывание по причине, которую я в настоящее время не понимаю.

Спасибо за любую помощь,

Ответы [ 4 ]

0 голосов
/ 04 июля 2018

Вы изменяете состояние напрямую, это не разрешено, в последнем примере вы все еще делаете это. Лучше использовать Object.assign(…) для создания нового объекта, подобного этому:

let newState = Object.assign({}, ...this.state,  running: response);

Тогда, только сделайте ваш setState() звонок

this.setState(newState);

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

0 голосов
/ 03 июля 2018

Вы можете попробовать изменить функцию checkIfRunning() {} на checkIfRunning = () => {}, чтобы передать this в функцию

0 голосов
/ 04 июля 2018

Спасибо всем за помощь, очень признателен.

Я решил проблему с помощью следующего исправления, хотя я не уверен, почему оно работает сейчас:

checkIfRunning() {
  return fetch('/api/following/iscurrentlyrunning', {
  credentials: 'include',
 })
.then(response => {
  console.log(response.status);
  if (response.status === 200) {
    return response.json();
  }
})
.then(response => {
  let cState = this.state;
  cState.running = response;
  this.setState({cState});
});

}

Обратите внимание, как this.setState (cState) стал this.setState ({cState}).

Спасибо всем за ваше время, это привело к интересным исследованиям с моей стороны.

0 голосов
/ 03 июля 2018

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

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

.then(response => {
    ...code here...
    // important! check that the instance is still mounted!
    if (this.setState) {
      this.setState(cState);
    }
});

Кроме того, вы никогда не должны изменять локальное состояние напрямую, как здесь:

// don't mutate state directly, use setState!
let cState = this.state;
cState.running = response;
...