Search code examples
javascriptreactjsreact-nativetimer

React Native - optimising ReactJS code for a timer app


I'm currently moving my ReactJS code to React Native and I was wondering if I need to update it in any way. It's working but I believe there might be a memory leak somewhere (I get a warning when running the app).

The part I'm referring to is:

class Stopwatch extends Component {

  constructor() {
    super();
    this.state = {
      timerOn: false,
      timerStart: 0,
      timerTime: 0
    };
  }

  startTimer = () => {
        this.setState({
          timerOn: true,
          timerTime: this.state.timerTime,
          timerStart: Date.now() - this.state.timerTime,
        });
        this.timer = setInterval(() => {
          this.setState({
            timerTime: Date.now() - this.state.timerStart
          });
        }, 10);
      };
    
    stopTimer = () => {
        this.setState({ 
          timerOn: false,
        });
        clearInterval(this.timer);
      };


    render() {
        return (
              <View>
                  {this.state.timerOn === false && this.state.timerTime === 0 && (
                    <TouchableOpacity style={styles.button} onPress={this.startTimer}>
                      <Text>start</Text>
                    </TouchableOpacity> 
                  )}
                  {this.state.timerOn === true && (
                    <TouchableOpacity style={styles.button} onPress={this.stopTimer}>
                      <Text>stop</Text>
                    </TouchableOpacity>
                  )}
              </View>
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>


Solution

  • If your component unmounts while the timer is running you will find a memory leak. This is because the setInterval never gets cleared; the interval callback will still fire, and since it calls setState it will try to update the component even though it is no longer mounted (leading to the error message)

    To solve this you just need to use the componentWillUnmount lifecycle method to clear the setInterval.

    https://reactjs.org/docs/state-and-lifecycle.html