【问题标题】:State of array is not updated in ComponentDidMountComponentDidMount 中的数组状态未更新
【发布时间】:2020-08-16 16:40:45
【问题描述】:

我有一个奇怪的情况,我有一个数组作为状态: this.state = { ActivityItem: []} 我正在从调用这样的 API 的库中向它推送值:

   getDataFromKit(dateFrom) {


                Kit.getSamples(stepCountSample, (err, results) => { //api call
                if (err) {
                    return;
                }
                const newData = results.map(item => { return { ...item, name: 'itemAmount' } });
                this.setState({ d: [...this.state.ActivityItem, ...newData] })

            })

然后,我从 ComponentDidMount() 调用此方法以加载要加载的数组

  componentDidMount() {
     this.getDataFromHealthKit(ONEDAYINTERVAL);
    console.log("values are", this.state.ActivityItem)
}

现在,最奇怪的部分是:不知何故,ComponentDidMount 中的数组是空的,但是当我显示 Array 的元素以返回 render() 函数时,它会显示所有正确添加的值。这怎么可能?我该如何解决?

【问题讨论】:

    标签: javascript arrays reactjs react-native components


    【解决方案1】:

    setState 本质上是异步的。因此,在设置状态后立即记录状态可以提供此行为,但如果设置正确,它将显示您的情况发生的所需内容。另外,componentDidMount 在开始时只调用一次,因此您可以在 componentDidUpdate 方法中检查日志。

    【讨论】:

      【解决方案2】:

      状态更新本质上是异步的。如果您想在类组件中设置状态后立即打印状态,则将函数传递给setState 的第二个参数。

      像这样

      componentDidMount() {
        this.getDataFromHealthKit(ONEDAYINTERVAL);
        // remove console.log   
      }
      ...
      
      
      getDataFromKit(dateFrom) {
          ...
         this.setState({ ActivityItem: [...this.state.ActivityItem, ...newData] }), () => {
          console.log("values are", this.state.ActivityItem) //<---- 
         }
      })
       ...
      }
      

      【讨论】:

        【解决方案3】:

        在更新状态值时使用prevstate。 React setState 是一个异步更新,并进行批量更新。使用prevState 确保在计算新的状态值之前更新状态值。

        getDataFromKit(dateFrom) {
            let stepCountSample = {
              startDate: dateFrom.toISOString(),
              type: "Type1"
            };
        
            Kit.getSamples(stepCountSample, (err, results) => {
              //api call
              if (err) {
                return;
              }
              const newData = results.map(item => {
                return { ...item, name: "itemAmount" };
              });
              this.setState(prevState => {
                ActivityItem: [...prevState.ActivityItem, ...newData];
              });
            });
          }
        

        DOCUMENTATION 有助于理解这个概念

        另外,console.log 不会直接给出更新的状态,因为状态更新是批处理的。您可以使用回调方法来设置状态函数。只有在成功更新状态值后回调才会运行

        【讨论】:

          猜你喜欢
          • 2017-04-25
          • 2016-03-01
          • 2019-06-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-03-22
          相关资源
          最近更新 更多