我怎么能写这个函数,这样它就不会每次都在 foreach 中设置状态

How could I write this function so it doesn't setState within the foreach everytime

该函数收集 SPO 中某个项目的角色 Assignment PrincipalIds。然后,我使用 foreach 将这些 PrincipalId 的标题填充到状态。这一切都很好,但效率很低,我相信有比多次渲染更好的方法。

private _permJeChange = async () => {
    if(this.state.userNames){
      this.setState({
        userNames: []
      });
    }
    var theId = this.state.SelPermJEDD;
    var theId2 = theId.replace('JE','');

    var info = await sp.web.lists.getByTitle('MyList').items.getById(theId2).roleAssignments();
    console.log(info, 'info');
   
    var newArr = info.map(a => a.PrincipalId);
    
    console.log(newArr, 'newArr');
    // const userIds = [];
    // const userNames = [];
    // const userNameState = this.state.userNames;
    newArr.forEach(async el => {
     
      try {
        await sp.web.siteUsers.getById(el).get().then(u => {
          this.setState(prevState => ({
            userNames: [...prevState.userNames, u.Title]
          }));
          // userNames.push(u.Title);
          //  userIds.push(el);
           
         });
       } catch (err) {
         console.error("This JEForm contains a group");
       }

     });

    
  }

我在其中留下了旧代码,以便您了解我的尝试。我最初尝试使用局部变量数组 const userNames = [] 但在本地甚至全局声明它会在每次填充数组时清除数组!所以那是不好的。

PS。有 try catch 的原因是处理任何分配有权限组的 SPO 项目。 RoleAssignments() 请求无法处理组,只能处理用户。

创建一个 Promise 数组并等待它们全部解决,然后进行单个状态更新。

const requests = info.map(({ PrincipalId }) => 
  sp.web.siteUsers.getById(PrincipalId).get().then(u => u.Title)
);

try {
  const titles = await Promise.all(requests);
  this.setState(prevState => ({
    userNames: prevState.userNames.concat(titles),
  }));
} catch (err) {
  console.error("This JEForm contains a group");
}