NightTom
NightTom

Reputation: 485

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

The function collects role Assignment PrincipalIds on an item in SPO. I then use a foreach to populate state with the Title's of these PrincipalIds. This all works fine but it's inefficient and I'm sure there is a better way to do it than rendering multiple times.

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");
       }

     });

    
  }

I've left old code in there to give you an idea of what I've tried. I initially tried using a local variable array const userNames = [] but declaring it locally or even globally would clear the array everytime the array was populated! So that was no good.

PS. The reason there is a try catch is to handle any SPO item that has a permissions group assigned to it. The RoleAssignments() request can't handle groups, only users.

Upvotes: 1

Views: 41

Answers (1)

Drew Reese
Drew Reese

Reputation: 203552

Create an array of Promises and await them all to resolve and then do a single state update.

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");
}

Upvotes: 1

Related Questions