Shivanshu Anand
Shivanshu Anand

Reputation: 61

the api block gets called 2 times, leads in rendering component twice, though conditions are getting checked properly

I am using 3 dynamic variable inside setInterval, in state

this.state={
   checked: true,
   currentHash:"some current hash",
   updating: true
}

inside componentDidMount, i've done something like this

componentDidMount = () => {
        let timer
        timer = setInterval( (checked, currentHash, updating) => {
            try {
                this.setState({analysis:true});
                if(checked){
                    var generatedHash = "current generated hash";
                                if (currentHash !== generatedHash) {
                                    currentHash = generatedHash;
                                    if(updating){
                                        this.setState({updating:false})
                                        const updateResponse = this.props.sendFile(DOCUMENT_ANALYSIS, ""); // my api call
                                        
                                    }
                                    else{
                                        this.setState({analysis:false})
                                    }
                                }
                                else{
                                    this.setState({analysis:false})
                                }
                    clearInterval(timer);
                    this.componentDidMount();
                }
                else{
                    clearInterval(timer);
                    this.setState({analysis:false});
                    this.componentDidMount();
                }
               
            }
            catch (error) {
                console.log("Event error", error);
            }
           
        }, 10000, this.state.checked, this.state.currentHash, this.state.updating)
    }

The interval is set to 10 seconds. But before getting correct state data, it is calling the same function twice.

Upvotes: 4

Views: 149

Answers (3)

Sohan Varnikar
Sohan Varnikar

Reputation: 16

I believe the timer variable should be accessable to the whole component instead of the function. Whats happening is, since the timer variable is only scoped to the running block, the clearInterval never clears it, but the timer is already set, so the rendering happens again.

Upvotes: 0

AetherPrior
AetherPrior

Reputation: 105

From the docs of ReactJS:

You may call setState() immediately in componentDidMount(). It will trigger an extra rendering, but it will happen before the browser updates the screen. This guarantees that even though the render() will be called twice in this case, the user won’t see the intermediate state. Use this pattern with caution because it often causes performance issues. In most cases, you should be able to assign the initial state in the constructor() instead. It can, however, be necessary for cases like modals and tooltips when you need to measure a DOM node before rendering something that depends on its size or position.

It appears that setInterval may be calling setState immediately.

Upvotes: 0

Cristian Zabala
Cristian Zabala

Reputation: 1

you can try this or you can try react hook can be better

  componentDidMount =()=> {
     this.time();
   }


  time =()=>{
      let timer
    timer = setInterval( (checked, currentHash, updating) => {
        try {
            this.setState({analysis:true});
            if(checked){
                var generatedHash = "current generated hash";
                            if (currentHash !== generatedHash) {
                                currentHash = generatedHash;
                                if(updating){
                                    this.setState({updating:false})
                                    const updateResponse = this.props.sendFile(DOCUMENT_ANALYSIS, ""); // my api call
                                    
                                }
                                else{
                                    this.setState({analysis:false})
                                }
                            }
                            else{
                                this.setState({analysis:false})
                            }
                clearInterval(timer);
                this.componentDidMount();
            }
            else{
                clearInterval(timer);
                this.setState({analysis:false});
                this.componentDidMount();
            }
           
        }
        catch (error) {
            console.log("Event error", error);
        }
       
    }, 10000, this.state.checked, this.state.currentHash, this.state.updating)
  }

Upvotes: 0

Related Questions