3

I want to update the state of a React component every 1000 ms. However, I tried doing setInterval on the componentDidMount, but with no luck. Currently I get two results in my console.log, the one is an empty state object in the constructor, and the other is the fetched object from the API. How do I update the state of the component every 1000 ms with setInterval?

This is my code:

let url = 'some-link-bla-bla';

class Basemap extends React.Component {

    constructor(props) {
        super(props);
        this.state = {};
        console.log(this.state);
    }

    render() {
        return (
            <Scene style={{ width: '100vw', height: '100vh' }} 
                    mapProperties={{ basemap: 'satellite' }} 
                    viewProperties={ this.state } />
        );
    }

    componentDidMount() {
        fetch(url)
            .then(d => d.json().then(function(d) {
                console.log(d);
            }))
            .then(d => function(d) {
                this.setState({
                  center: [
                      {latitude : d.iss_position.latitude} + ', ' + 
                      {longitude: d.iss_position.longitude}
                    ]
                })
            });
    }
}

export default Basemap;
2
  • 2
    Could you add the code of your attempt with setInterval. Your code has none Commented Aug 31, 2017 at 13:12
  • @IsaaK08, If you found the right solution here, set it as Accepted. Commented Jan 11, 2018 at 10:32

2 Answers 2

6

I moved the call to the fetch method with in the getCenter method, which I will pass to setInterval function with in componentDidMount

  • Call this.getCenter() before you set the interval. It will fetch immediately after mounting the component.

  • Clear the interval with in componentWillUnmount. It will make sure you setInterval does not trigger any fetch request after unmounting the component.

    let url = 'some-link-bla-bla';
    
    class Basemap extends React.Component {
    
    constructor(props) {
        super(props);
        this.state = {};
        console.log(this.state);
    }
    
    render() {
        return (
            <Scene style={{ width: '100vw', height: '100vh' }} 
                    mapProperties={{ basemap: 'satellite' }} 
                    viewProperties={ this.state } />
        );
    }
    
    componentDidMount() {
        // Call this function so that it fetch first time right after mounting the component
        this.getCenter();
    
        // set Interval
        this.interval = setInterval(this.getCenter, 1000);
    }
    
    componentWillUnmount() {
        // Clear the interval right before component unmount
        clearInterval(this.interval);
    }
    
    getCenter = () => {
        fetch(url)
                .then(d => d.json().then(function(d) {
                    console.log(d);
                }))
                .then(d => function(d) {
                    this.setState({
                      center: [
                          {latitude : d.iss_position.latitude} + ', ' + 
                          {longitude: d.iss_position.longitude}
                        ]
                    })
                });
    }
    }
    
    export default Basemap;
    
Sign up to request clarification or add additional context in comments.

2 Comments

This worked for me. Only had to change getCenter in the mount to this.getCenter()
setInterval only seems to fire once and then stop for me.
3

Normally with React I use setTimeout instead of setInterval the only counterpart is that you need to call it once the function ended.

let url = 'some-link-bla-bla';

class Basemap extends React.Component {

    constructor(props) {
        super(props);
        this.state = {};
        console.log(this.state);
        this.intervalFunc = this.intervalFunc.bind(this); // Here
        this.timeout= this.timeout.bind(this); // Here
    }

    render() {
        return (
            <Scene style={{ width: '100vw', height: '100vh' }} 
                    mapProperties={{ basemap: 'satellite' }} 
                    viewProperties={ this.state } />
        );
    }

    intervalFunc() {
        fetch(url)
            .then(d => d.json().then(function(d) {
                console.log(d);
            }))
            .then(d => function(d) {
                this.setState({
                  center: [
                      {latitude : d.iss_position.latitude} + ', ' + 
                      {longitude: d.iss_position.longitude}
                    ]
                })
                this.timeout(); // Here
            });
    }

    timeout() {
        this.setTimeout(intervalFunc, 1000); // Here
    }

    componentDidMount() {
        this.timeout(); // Here
    }
}

8 Comments

This seems like appropriate solution, but I get: Line 35: 'timeout' is not defined no-undef Line 40: 'intervalFunc' is not defined no-undef Line 44: 'timeout' is not defined no-undef
Sorry, forgot to add this.timeout()
Code changed, changed setTimeout() to this.setTimeout() on timeout()
Recursive timeout function. Neat stuff.
@JosephCho Why is it neat? What if the server-side returns an error, will you try requests endlessly until it gets working by magic? This way it only calls another timeout if the last was successfull. I'm not saying it's better than setInterval because it's not, setInterval was made for this cases. Just another way to do it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.