ComponentDidMount代码即使在组件卸载后仍执行

时间:2019-08-14 11:35:40

标签: javascript reactjs react-redux es6-promise

在ComponentDidMount()内部,我们定期调用api以获取数据。但是即使在组件卸载后,仍然会调用api。

async componentDidMount() {
    let { getItemHistoryData } = this.props;

    for (let i = 0; i < 25 && !this.props.is_synched; i++) {
        await wait(5000);
        getItemHistoryData();
    }
}


const wait = (ms) => {
    return new Promise(resolve => setTimeout(resolve, ms));
}

但是,即使用户移至另一个页面,也会调用getItemHistoryData()操作。

4 个答案:

答案 0 :(得分:0)

我认为您需要重构一下代码...

您需要跟踪setTimeout才能将其停在componentWillUnmount()

let t;
async componentDidMount() {
  let { getItemHistoryData } = this.props;

  t = setTimeout(getItemHistoryData(), 5000);
}


componentWillUnmount() {
  clearTimeout(t);
  t = null;
}

getItemHistoryData() {

   // Do the function's stuff here

   if(!this.props.is_synched){
      t = setTimeout(getItemHistoryData(), 5000);
   }

}

i < 25 && !this.props.is_synched末尾做关于getItemHistoryData()的事情,然后再次调用-或不调用setTimeout

答案 1 :(得分:0)

componentDidMount运行并完成。但是它有一个Promise,当实现时,它将在Promise内部调用回调。这是由javascript引擎完成的。与反应无关。

编辑:看起来for循环确实被完全执行,但是在await处阻塞。因此,它创建了一个承诺链,而不是一次创建25个承诺。需要做更多的研究。我虽然只有for-of循环能做到这一点。很抱歉提供错误信息。

这是您的代码转换为es5 Converted code with Babel JS

时的样子

答案 2 :(得分:0)

我为您提供了更多我喜欢使用的选项

保存状态:

 intervalId: null,
 intervalCounter: 0

和componentDidMount添加:

const intervalId = setInterval(this.timer, 5000, 25)

创建一个新功能timer

timer = async () => {
    if(this.state.intervalCounter <= 25){
        getItemHistoryData();
        this.setState({intervalCounter: this.state.intervalCounter + 1})
    } else {
        clearInterval(this.state.intervalId); //clear
    }
}

并且不要忘记清除用户离开屏幕时的间隔:

  componentWillUnmount() {
       clearInterval(this.state.intervalId);
   }

答案 3 :(得分:0)

从上面的代码中我了解到,即使卸载了组件,循环也一直运行到完成。为了解决这种特殊情况而无需在代码中进行重大更改,您可以使用布尔值来跟踪组件的卸载,并在循环条件中使用它来确保循环在卸载之后的迭代中退出。请注意,卸载组件后,此操作仍将执行挂起的任务。

async componentDidMount() {
    let { getItemHistoryData } = this.props;

    for (let i = 0; i < 25 && !this.props.is_synched && !this.isUnmounted; i++) {
        await wait(5000);
        getItemHistoryData();
    }
}

async componentWillUnmount(){    
    this.isUnmounted = true;
}

如果要防止进一步的迭代,可以重构代码以使用 setInterval ,然后使用 clearInterval 进行清理。对于大多数实际情况,我上面建议的方法应足够并且可以防止代码重构。