1

I am writing a website using react . In one component I have a setInterval() function which gets executed, it updates them DOM. Now, when I change onto another site with my router (react-router-dom) the setInterval() function crashed, because it cannot find the DOM elements to update. How do I go on about this? I though I use componentWillUnmount() but the same error occurs.

class Counter extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            stop: false,
        }
    }

    componentWillUnmount() {
        if(!this.state.stop) {
            this.setState({
                stop: true,
            })
        }
    }

    _stop = (counter) => {
        clearInterval(counter);
    }

    _someFunc = () =>  {
        ...
    }

    render() {
        ...
        const update = setInterval(function () {
            document.getElementById('some-id').innerText = this._someFunc();
        }, 1000);

        if(this.state.stop) {
            this._stop(update)
        }

        return (
                <p id='some-id'></p>
        )
    }
}

export default Counter;

TypeError: document.getElementById(...) is null.

How do I stop the interval?

four-eyes
  • 10,740
  • 29
  • 111
  • 220

2 Answers2

1

Changes:

1- Put the timer outside of the render method, better to use componentDidMount lifecycle method. By this way timer will be registered only once and after each 1ms it will execute the callback method.

2- Store the timer id in a variable (in instance) to stop it before leaving the page.

Like this:

class Counter extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            stop: false,
        }
    }

    componentDidMount() {
        this.timerId = setInterval(function () {
            document.getElementById('some-id').innerText = this._someFunc();
        }, 1000);
    }

    componentWillUnmount() {
        this._stop();
    }

    _stop = () => {
        clearInterval(this.timerId);
    }

    _someFunc = () =>  {
        ...
    }

    render() {

        return (
                <p id='some-id'></p>
        )
    }
}

export default Counter;
Mayank Shukla
  • 100,735
  • 18
  • 158
  • 142
  • Ah, so its only the `this.timerId = setInterval ...` thats different to `const update = setInterval....`? Why do I need to store it in a class(?) variable and cannot store the interval the way I did it? – four-eyes Aug 30 '18 at 13:59
  • if you set the value in local variable, it will not be available in all the functions. if you store in class instance it will be available easily. – Mayank Shukla Aug 30 '18 at 14:02
  • also issue with your code was, on each re-rendering of the component a new timer will be registered instead of using the same, to avoid that put a check before using setInterval :) – Mayank Shukla Aug 30 '18 at 14:10
0

If it is not a performance optimization then do it react way

https://stackoverflow.com/a/39426527/6124657

xadm
  • 8,219
  • 3
  • 14
  • 25