Javascript映射函数是异步的吗?

时间:2019-08-27 19:42:59

标签: javascript arrays reactjs

我正在更新map内的状态元素的属性

  computePiePercentages(){
    var denominator = 1600
    if (this.state.total < 1600){
      denominator = this.state.total
    }

    return this.state.pieChartData.map((item, index) => {
      return {
        ...item,
        y: Number((item.y / denominator).toFixed(1)) * 100
      }
    })
}

但是,当我使用pieChartData显示图表时-y尚未更新。我检查了数学公式以确保在computePiePercentages

中将其设置为正确的值

map函数是否像setState一样异步?在显示结果之前,如何确保等待更新发生?

以下是相关代码的其余部分:

class Budget extends React.Component {
computePiePercentages(){
    var denominator = 1600
    if (this.state.total < 1600){
      denominator = this.state.total
    }

    return this.state.pieChartData.map((item, index) => {
      return {
        ...item,
        y: Number((item.y / denominator).toFixed(1)) * 100
      }
    })
}


    computeTotals(){
    var runningTotal = 0
    var pieArray = []
    var beyondBudget = {}

    Object.entries(this.state.data.selectedQuestions).map((element, j)  => {
      console.log("hi here")
      console.log(element)
    //return selectedQuestions.map((val, j) => {
      const value = Object.values(element[1])[0]
      const name = element[0]

      runningTotal += value
      if(runningTotal <= 1600){
        let pieSlice =
             {
               x: name,
               y: value
             };
        pieArray = pieArray.concat(pieSlice)

      }
      else {

            if (Object.keys(beyondBudget).length == 0) {
                beyondBudget[name] = {};
                beyondBudget[name] = runningTotal - 1600;
                let pieSlice =
                     {
                       x: name,
                       y: value - (beyondBudget[name])
                     };
                pieArray = pieArray.concat(pieSlice)
            }
            if (!beyondBudget[name]) {
                beyondBudget[name] = {};
            }
            if (Object.keys(beyondBudget).length > 1) {
                beyondBudget[name] = value;
            }

        }
    });

    this.setState({
      pieChartData: pieArray,
      total: runningTotal,
      beyondBudget: beyondBudget,
    }, () => {
      this.computePiePercentages();
    });

}


  render() {
      const {
          data,
          pieChartData,
          beyondBudget,
          showResults,
          total
      } = this.state;
      const questions = data.questions;
      return (
          <div>
              {questions.map((q, i) => (
                  <UL key={i}>
                      <li>
                          <h4>{q.text}</h4>
                      </li>
                      <li>
                          <Options
                              state={this.state}
                              q={q}
                              i={i}
                              handler={this.handleInputChange}
                          />
                      </li>
                  </UL>
              ))}
              <button onClick={(event) => {
                this.computeTotals();
                this._showResults(true);
              }}>Click</button>
              {console.log(this.state.showResults)}
                {this.state.showResults &&
                  (<div>
                        <VictoryPie
                            colorScale="blue"
                            data={pieChartData}
                            labels={d => `${d.x}: ${d.y}%`}
                            style={{ parent: { maxWidth: '50%' } }}
                        />

                        {Object.keys(beyondBudget).length > 0 && (
                            <div>
                                <Table>
                                    <tbody>
                                        <tr>
                                            <th>Out of Budget</th>
                                        </tr>
                                        <BrokeBudget
                                            beyondBudget={beyondBudget}
                                        />
                                    </tbody>
                                </Table>
                            </div>
                        )}
                    </div>
                  )
                }
          </div>
      );
  }
  }

1 个答案:

答案 0 :(得分:1)

正如其他人所提到的,数组的.map()函数返回一个新数组,而不更改旧数组。因此,目前的this.computePiePercentages()会基于this.state.pieChartData创建一个新数组并返回该新数组。此操作不会更改this.state.pieChartData

您正在从this.computePiePercentages()的回调函数中调用this.setState()。这只是一个函数,除了setState()完成更改状态时会调用之外,没有其他特殊属性。因此,要在computePiePercentages()内进一步更新状态,您需要再次调用setState()

有两种选择:

  1. 使用返回值this.computePiePercentages更新回调函数中的状态:
this.setState({
  pieChartData: pieArray,
  total: runningTotal,
  beyondBudget: beyondBudget,
}, () => {
  this.setState({
    pieChartData: this.computePiePercentages()
  });
});
  1. 更新this.computePiePercentages中的状态:
this.setState({
  pieChartData: this.state.pieChartData.map((item, index) => {
    return {
      ...item,
      y: Number((item.y / denominator).toFixed(1)) * 100
    }
  })
});