setState is updating immediately even after using setTimeOut

前端 未结 3 1349
孤独总比滥情好
孤独总比滥情好 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);
      );
    }
    

提交回复
热议问题