【问题标题】:React wait for one loop (and setState) to finish before another loop反应等待一个循环(和 setState)在另一个循环之前完成
【发布时间】:2020-09-10 20:51:32
【问题描述】:
 handleSubmit = () => {
    this.setState({ modalState: false })

    this.state.codeToClass.forEach((code, classId, map) => {
      const cr = _.find(this.state.classRoles, { id: classId })

      if (code === cr.classCode) {
        console.log('here')
        this.setState(state => ({ 
          classRoles: state.classRoles.map((cc) => {
            console.log(cc.id)
            console.log(classId)
            console.log(cc.id === classId)
            if (cc.id === classId) {
              console.log('here1')
              return {
                ...cc,
                role: 'TA',
              }
            }
            console.log('what')
            return cc
          }),
        }), ()=> console.log(this.state.classRoles)) //this is called later
        
      } else {
        NotificationManager.error('Failed to register as TA.')
      }
    })
    console.log(this.state.classRoles) //this is called first
    this.state.classRoles.forEach((c) => {
      if (c.role === '') {
        api.deleteClassUser(c.id, this.state.user.id)
      } else {
        api.postAddClass(c.id, this.state.user.id, c.role)
        console.log(c)
      }
    })

    EventEmitter.publish('currentlyEnrolled', this.state.classRoles)
  }

我正在尝试在第一个 forEach 完成后运行第二个 forEach,即状态已更新。但它一直按此顺序运行。有没有办法解决这个问题?

【问题讨论】:

    标签: javascript reactjs foreach state


    【解决方案1】:

    Promise 是你的朋友。

    // You map your operations in to Promises.
     const promises = this.state.codeToClass.map((code, classId, map) => {
       return new Promise(resolve=>{
          const cr = _.find(this.state.classRoles, { id: classId })
    
          if (code === cr.classCode) {
            console.log('here')
            this.setState(state => ({ 
              classRoles: state.classRoles.map((cc) => {
                console.log(cc.id)
                console.log(classId)
                console.log(cc.id === classId)
                if (cc.id === classId) {
                  console.log('here1')
                  return {
                    ...cc,
                    role: 'TA',
                  }
                }
                console.log('what')
                return cc
              }),
            }), ()=> resolve()) //this is called later
            
          } else {
            NotificationManager.error('Failed to register as TA.')
          }
        })
    })
    
    // and then you wait for all of the promises
    
    await Promise.All(promises);
    // then continue to execution
    

    【讨论】:

      【解决方案2】:

      有两种选择。

      1. 使用承诺
      2. 异步等待

      既然map可以和await一起使用,我觉得

      const tempState = this.state.codeToclass;
      await tempState.map(...
      

      这种方式可行:)

      【讨论】:

      • 是的,他确实应该需要使用 Promise,但该方法不可等待。
      【解决方案3】:

      this.setState 是一个异步操作。

      你可以试试这样的:

      handleSubmit = () => {
         //some code...
         
         this.setState(state => ({
            state.codeToClass.forEach((...args) => {
               //logic to update the state...
            });
         }), setClassRoles); //call a function after the state value has updated
         
      }
      
      setClassRoles = () => {
          this.state.classRoles.forEach((...args) => {
              //your code...
          });
          EventEmitter.publish('currentlyEnrolled', this.state.classRoles)
      }
      

      【讨论】:

      • 这是一个很好的方法,但是 foreach 需要在 setState 函数中才能满足 OPs 的要求。
      猜你喜欢
      • 2019-09-24
      • 1970-01-01
      • 2020-04-20
      • 2021-02-15
      • 2022-10-12
      • 1970-01-01
      • 1970-01-01
      • 2023-04-05
      • 2015-03-04
      相关资源
      最近更新 更多