反应setState竞争条件

时间:2018-09-20 09:45:28

标签: reactjs

我正在构建一个React组件,该组件在后台进行很多调用来收集数据。 我希望View尽可能快地响应,并在获取数据后尽快加载它。但是,这会导致在正确处理状态时出现比赛条件。

有时候,一个实验结果会使另一个实验结果不稳定。 如何正确处理这种并行性?

const ctrl = this;
this.state.experiments.foreach((experiment) => {
    this.props.ReportV4.kpi({
        experimentId: experiment.id
    }).then(function (report) {
        experiment.kpi.significant = report.significanceReached;
        experiment.kpi.uplift = report.uplift || "N/A";

        ctrl.setState({
            experiments: update(ctrl.state.experiments, {[experiment.key]: {$set: experiment}})
        });
    });
});

2 个答案:

答案 0 :(得分:0)

是的,这就是JavaScript作为单线程语言维护其回调堆栈的方式。您的循环将在堆栈中创建某些回调。我想建议您将experiments对象作为类属性进行维护。它将在接收时包含所有回调数据。

在构造函数中:

constructor(props) {
    super(props);
    this.experiment= {};
}

在承诺回调中:

// populate your experiment whit significant & uplift etc.

this.experiments[experiment.key] = experiment;

this.setState({
    experiments: this.experiments
});

您可以使用它们的键名来呈现这些实验,而无需遍历实验。

我希望这会对您有所帮助。

答案 1 :(得分:-1)

如果这样可以解决您的问题,那么如何在下面编写这样的代码呢?

let numberofExp = this.state.experiments.length;
    function callApi(){
        if(numberofExp>0){
            this.props.ReportV4.kpi({
                experimentId: experiment.id // change accordingly
            }).then( (report) =>{
                numberofExp--;
                experiment.kpi.significant = report.significanceReached;
                experiment.kpi.uplift = report.uplift || "N/A";
                this.setState({
                    experiments: update(this.state.experiments, { [experiment.key]: { $set: experiment } })
                },()=>this.callApi());
            });
        }
        else{
            return
        }
    }