Murakami
Murakami

Reputation: 3760

Launching interval after updating props in React.js

I'd like to fire interval after backend data will come in as a prop. Take a look at this chunk of code:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { getAdvert } from "../../actions/advert";
import './_advert.scss';

class Advert extends Component {
  state = { counter: 0 };

  componentDidMount() {
    const { getAdvert } = this.props;

    getAdvert();
  }

  componentWillReceiveProps(nextProps) {
    const { counter } = this.state;

    this.bannerInterval = setInterval(() => {
      this.setState({ counter: counter === Object.keys(nextProps.banners).length - 1 ? 0 : counter + 1 });
    }, 1000) 
  }

  render() {
    const { banners } = this.props;
    const { counter } = this.state;

    return (
      <div className="advert__container">
        <img src={banners[counter] && banners[counter].image_url} alt="advert" />
      </div>
    );
  }
}

const mapStateToProps = ({ banners }) => {
  return { banners };
};

const mapDispatchToProps = (dispatch) => {
  return {
    getAdvert: () => dispatch(getAdvert())
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(Advert);

So as you can see I tried to run it within componentWillReceiveProps method as I thought it might be proper place to be dependent on incoming props. But that won't work. I will run only once and interval will be repeating the same value.

Thanks for helping!

Upvotes: 1

Views: 39

Answers (1)

Mos&#232; Raguzzini
Mos&#232; Raguzzini

Reputation: 15821

ComponentWillReceive props is extremely dangerous used in this way. You are istantiating a new interval every time a props is received without storing and canceling the previous one. Also is not clear how do you increment counter, as I see the increment in your ternary will not increase the counter value incrementaly.

// This is an example, the lifeCylce callback can be componentWillReceive props
componentDidMount() { 
   const intervalId = setInterval(this.timer, 1000);
   // store intervalId in the state so it can be accessed later:
   this.setState({intervalId: intervalId});
}

componentWillUnmount() {
   // use intervalId from the state to clear the interval
   clearInterval(this.state.intervalId);
}

timer = () => {
   // setState method is used to update the state with correct binding
   this.setState({ currentCount: this.state.currentCount -1 });
}

Upvotes: 2

Related Questions