React setState in a map function

前端 未结 3 1673
渐次进展
渐次进展 2021-01-28 08:44

I cannot wrap my head around the issue below.

The issue relates to the asynchronous setState dimension. Usually I use the callback, but doesn\'t seem appropriate here.

相关标签:
3条回答
  • 2021-01-28 08:56

    You can't do what you are trying here with setState because it is asynchronous and will conflict with the different states available on each iteration in that for () loop.

    What you can do is extract the state first, manipulate it as needed, then run setState (at least in this one below)

    .then(data => {
        // Pull out what you want to mess with here first
        const users = [ ...this.state.users ];
        const dataValObj = data.val();
    
        // Then use spread operator (or Object.assign/Array.concat)          
        this.setState({
          users: [ 
              ...users, 
              ...Object.keys(dataValObj)
          ],
          ...dataValObj
        });
    })
    

    And it seems you followed a similar pattern throughout the code. Try and apply what I've done here to the other areas that are using loops with setState inside them.

    0 讨论(0)
  • 2021-01-28 08:56

    Just use second argument in this.setState.

    Second argument is a function that will be called after seting State.

    this.setState({ name:value },() => {this.nameOfTheFunctionYouWantToRunNext() });

    0 讨论(0)
  • 2021-01-28 09:14

    found one way to do it using promise all below. It allows me to remove the setState from the loop and directly work on it instead of have to rely on 2 setstate. Both comments/answer helped me to process that,

      getUserPoints = () => {
    this.state.users.map(user => {
      // Create the dynamic name of the state, 1 for each user
      let userPoints = `${user}points`;
    
      // initializing the state for userPoint to be at 0 for future calculation
      this.setState({ [userPoints]: 0 });
    
      let userCounter = 0;
      let promiseArrays = [];
      this.state[user].map(player => {
        let promise = database
          .ref(`players/${player}`)
          .child("points")
          .once("value")
          .then(data => {
            let points = parseInt(data.val());
            return (userCounter = userCounter + points);
          });
        promiseArrays.push(promise);
      });
      Promise.all(promiseArrays).then(() =>
        this.setState({
          userArrayPoints: this.state.userArrayPoints.concat({
            [user]: userCounter
          })
        })
      );
    });
    

    };

    0 讨论(0)
提交回复
热议问题