setState is updating immediately even after using setTimeOut

前端 未结 3 1347
孤独总比滥情好
孤独总比滥情好 2021-01-24 02:13

I have a div with 10 elements, which are to be updated one-by-one with a time delay of say 2secs. Below is the code for the same

for(let boxNo=0; boxNo<10; bo         


        
相关标签:
3条回答
  • 2021-01-24 02:38

    You're breaking two of the fundamental rules of React:

    1. Don't mutate state directly

      for(let boxNo=0; boxNo<10; boxNo++){
        setTimeout(() => {
          nodes[boxNo].isMarked = true; // <==== here
          this.setState({nodes});
          }, (boxNo*200)+boxNo);
        );
      }
      
    2. If updating state based on existing state, use the callback form because state updates may be asynchronous (and in any case, in your example, time has passed):

      for(let boxNo=0; boxNo<10; boxNo++){
        setTimeout(() => {
          nodes[boxNo].isMarked = true;
          this.setState({nodes});       // <==== here
          }, (boxNo*200)+boxNo);
        );
      }
      

    Instead, see *** comments and associated code:

    // **IF** `nodes` is an array
    for(let boxNo=0; boxNo<10; boxNo++){
      setTimeout(() => {
        // *** Note using callback form (#2)
        this.setState(({nodes} => {
            // *** *Copy* the parts of state you're going to modify (#1)
            nodes = [...nodes];
            nodes[boxNo] = {...nodes[boxNo], isMarked: true};
            return {nodes};
        });
        }, (boxNo*200)+boxNo);
      );
    }
    

    that setState call can also be written like this at the (trivial) expense of creating a temporary object:

    this.setState(({nodes} => ({
        nodes: Object.assign([], nodes, {[boxNo]: {...nodes[boxNo], isMarked: true}})
    });
    

    or

    // **IF** `nodes` is a non-array object
    for(let boxNo=0; boxNo<10; boxNo++){
      setTimeout(() => {
        // *** Note using callback form (#2)
        this.setState(({nodes} => {
            // *** *Copy* the parts of state you're going to modify (#1)
            return {
                nodes: {
                    ...nodes,
                    [boxNo]: {...nodes[boxNo], isMarked: true}
                }
            };
        });
        }, (boxNo*200)+boxNo);
      );
    }
    
    0 讨论(0)
  • 2021-01-24 02:42

    setTimeout is calculating the 200 in your loop first time.

    try to increase the time with more milliseconds.

    3 seconds (3000 milliseconds)

        for(let boxNo=0; boxNo<10; boxNo++){
    (function(x){
          setTimeout(function(){
            nodes[boxNo].isMarked = true;
            this.setState({nodes});
            }, ((x+1)*3000)+x);}
          )(boxNo);
        }
    
    0 讨论(0)
  • 2021-01-24 03:00

    This works for fine for me.

     (function loop (boxNo) {          
      setTimeout(function () {   
         nodes[boxNo].isMarked = true;
         this.setState({nodes});                
         if (--boxNo) loop(boxNo);    // decrementing i and calling loop function again if i > 0
      },  ((boxNo+1)*2000)+boxNo)
    })(10);
    
    0 讨论(0)
提交回复
热议问题