ReactJS:未捕获(承诺)this.setState不是函数

时间:2018-07-02 23:08:26

标签: javascript reactjs binding promise setinterval

我正在处理以下令人沮丧的错误:

Home.js:231未捕获(承诺)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 :(得分:1)

承诺是有保证的未来,这意味着一旦调用,整个承诺链就会触发,并且您无能为力。

从实际的角度来看,这意味着您需要检查以确保在尝试访问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;

答案 1 :(得分:0)

您可以尝试将功能checkIfRunning = () => {}更改为this,以将dist传递给功能

答案 2 :(得分:0)

非常感谢您的帮助。

我通过以下修复方法解决了该问题,尽管不确定为什么现在可以解决该问题:

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})。

感谢您的宝贵时间,这为我带来了有趣的研究。

答案 3 :(得分:0)

您正在直接更改状态,这是不允许的,在最后一个示例中,您仍在这样做。最好使用Object.assign(…)创建这样的新对象:

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

然后,仅拨打您的setState()电话

this.setState(newState);

React的基本原理之一是对State的更改不是直接完成,而是使用setState函数,该更改会将更改放入队列,并且可以单独进行或通过批处理更新来完成。