2
votes

I have two functions in React Native Component, in that one should refresh every 10s and another one should refresh every 1s. I have implemented setInterval() function for refreshing on componentDidMount() and clearInterval() on componentWillUnmount(), but am facing trouble it takes only one function which has the lowest duration. But am achieving result if set duration of both function same duration.

Here is the example

...
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      btLevel: 0,
      btState: null,
    };
  }
  componentDidMount() {
    this.getBtLevels();
    this.getBtState();
    this.batLS2();
    this.batLS10();
  }
  componentWillUnmount() {
    clearInterval(() => { this.batLSS(); this.batLS10(); });
  }
  getBtLevels = () => {
    fetch(apiUrl).then((res) =>
      this.setState({btLevel: res.level}),
    );
  };
   getBtLevelArcs = () => {
      fetch(apiUrl).then((res) =>
      this.setState({btLevelArc: res.level}),
    );
   };

  getBtState = () => {
     fetch(apiUrl).then((res) =>
      this.setState({BtState: res.state}),
    );
  };
  
   batLS10 = () => {
     setInterval(() => {
      this.getBtLevelArcs();
  
    }, 10000);
   };
  batLS2 = () => {
    setInterval(() => {
       this.getBtLevels();
       this.getBtState();
    }, 1000);
  };

...

On the above Code this.getBtLevels(); this.getBtState(); fetch value every 1 seconds and this.getBtLevelArcs(); fetch value every 10 secounds. In this this.getBtLevels(); this.getBtLevelArcs(); functions get same value. But one should refresh every 1 second and another one every 10 seconds. Here am getting is 1s setInterval function this.batLS2() is refresh whole component.

How can I achieve this one should refresh value 1s and another 10s.

here is the Original Version code. Expo

2
clearInterval works by being passed the reference returned from setInterval, i.e. this.timerId = setInterval(... and clearInterval(this.timerId). - Drew Reese
@DrewReese I appreciated that, but can you brief with example. - Fussionweb
Combining @shubham Answer its work - Fussionweb

2 Answers

2
votes

Issue

clearInterval works by being passed the reference returned from setInterval, i.e. this.timerId = setInterval(... and clearInterval(this.timerId).

What I suspect is occurring is you edited you code and ran, which set an interval callback (but didn't clear it), and then edited and re-ran your code, which sets another interval callback (again, not cleared), etc... You basically aren't cleaning up the interval callbacks when the component unmounts (like a page refresh).

Solution

Add a timer variable for each interval timer

constructor(props) {
  super(props);
  
  ...

  this.timer1 = null;
  this.timer2 = null;
}

Clear each interval on dismount

componentWillUnmount() {
  clearInterval(this.timer1)
  clearInterval(this.timer2)
}

Save the timer ref

batLS10 = () => {
  this.timer2 = setInterval(() => {
    this.getBtLevelArcs();
  }, 10000);
};

batLS2 = () => {
  this.timer1 = setInterval(() => {
    this.getBtLevels();
    this.getBtState();
  }, 1000);
};

Edit nostalgic-snow-iqx3u

1
votes

What I understood by the example and statement is you want getBtLevels and getBtState to be called after every 1 sec and getBtLevelArcs after every 10 seconds. But what happens is when getBtState and getBtLevels invoke, their setState updates the whole component, which is not acceptable in your case.

Ideally this should not be a problem, because all the three functions have different states. btLevel, btLevelArc and btState. Updating one state should not impact the other one. But that totally depends upon your UI logic.

If that is still a problem: what you can do. You can split your component into two components. First one will hold the UI related to getBtLevels and getBtState and second component will contain UI related to getBtLevelArcs. This is required because setState will re-render the whole component.

Code will be something like this:

class App extends React.Component {
    ...
    //some common handlers for SubApp1 and SubApp2
    ...

    render() {
        return (
            <React.Fragment>
                <SubApp1 />
                <SubApp2 />
            </React.Fragment>
        )
    }    





class SubApp1 extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            btLevel: 0,
            btState: null,
        };
    }

    componentDidMount() {
        this.getBtLevels();
        this.getBtState();
        this.batLS2();
    }

    componentWillUnmount() {
        clearInterval(() => { this.batLSS(); });
    }
    getBtLevels = () => {
        fetch(apiUrl).then((res) =>
            this.setState({ btLevel: res.level }),
        );
    };


    getBtState = () => {
        fetch(apiUrl).then((res) =>
            this.setState({ BtState: res.state }),
        );
    };

    batLS2 = () => {
        setInterval(() => {
            this.getBtLevels();
            this.getBtState();
        }, 1000);
    }
      ...
      ...


class SubApp2 extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            btLevelArc: 'some default value'
        };
    }
    componentDidMount() {
        this.batLS10();
    }
    componentWillUnmount() {
        clearInterval(() => { this.batLS10(); });
    }
    getBtLevels = () => {
        fetch(apiUrl).then((res) =>
            this.setState({ btLevel: res.level }),
        );
    };

    getBtState = () => {
        fetch(apiUrl).then((res) =>
            this.setState({ BtState: res.state }),
        );
    };


    getBtLevelArcs = () => {
        fetch(apiUrl).then((res) =>
            this.setState({ btLevelArc: res.level }),
        );
    };
     ...
     ...