React JS - why is setState obeyed in some cases but not in others?

React JS - why is setState obeyed in some cases but not in others?
0

#1

My apologies for the noob question but this just isn’t making sense and I cannot find an answer for this either here or on places like StackOverflow.

I have written functions that change (set) State. But it looks like there are extra steps I need to take in some cases and I cannot divine what those are.

Specifically, I am changing the state of runRate in the slowDown and speedUp functions (I verified this with the console) but there is no visible effect on the rate of rendering.

What am I missing?

The CodePen for this is here

var ButtonsAndGrid = React.createClass({
  getInitialState: function() {
    return {
      gameStatus: 'stopped',
      currentData: [],
      totalColumns: 30,
      totalRows: 30,
      runRate: 100,
      fastestRunRate: 10,
      slowestRunRate: 1000,
      generation: 0,
      pausestatus: 0,
      pausebutton: 'Pause'
    };
  },


  switchColors: function() {
    var evaluatedArray = this.state.currentData;
    var newArray = [];
    
    var evaltotal = this.state.totalColumns * this.state.totalRows;
    var i;
    if(this.state.pausestatus === 0){
    for ( i = 0; i < evaltotal; i++) {
      
      var adjacent = 0;
      
      if(evaluatedArray[i] === 'red'){
        if(evaluatedArray[i + this.state.totalColumns]==='red')
          {adjacent++}
          if(evaluatedArray[i + this.state.totalColumns -1]==='red')
          {adjacent++}
          if(evaluatedArray[i + this.state.totalColumns + 1]==='red')
          {adjacent++}
        if(evaluatedArray[i - this.state.totalColumns]==='red')
          {adjacent++}
          if(evaluatedArray[i - this.state.totalColumns - 1]==='red')
          {adjacent++}
          if(evaluatedArray[i - this.state.totalColumns + 1]==='red')
          {adjacent++}
          if(evaluatedArray[i + 1]==='red')
          {adjacent++}
        if(evaluatedArray[i - 1]==='red')
          {adjacent++}
      
    
          if(adjacent > 3 ){newArray.push('white');}
	          else if(adjacent < 2 ){newArray.push('white');}
	          else{newArray.push('red');}
        
      }
      
      if(evaluatedArray[i] === 'white'){
        if(evaluatedArray[i + this.state.totalColumns]==='red')
          {adjacent++}
          if(evaluatedArray[i + this.state.totalColumns -1]==='red')
          {adjacent++}
          if(evaluatedArray[i + this.state.totalColumns + 1]==='red')
          {adjacent++}
        if(evaluatedArray[i - this.state.totalColumns]==='red')
          {adjacent++}
          if(evaluatedArray[i - this.state.totalColumns - 1]==='red')
          {adjacent++}
          if(evaluatedArray[i - this.state.totalColumns + 1]==='red')
          {adjacent++}
          if(evaluatedArray[i + 1]==='red')
          {adjacent++}
        if(evaluatedArray[i - 1]==='red')
          {adjacent++}
      
    
          if(adjacent === 3 ){newArray.push('red');}
	          else{newArray.push('white');}
        
      }
      
   }
    
    this.setState({
      currentData: newArray
    });
              }else{
                      this.setState({
                            currentData: currentData
                            });
                }
   },

   componentWillMount: function() {
       this.getRandom();
    },
   componentDidMount: function() {
       this.run();
    },

  getRandom: function() {  
     var tempArr = [],
     gridtotal = this.state.totalColumns * this.state.totalRows;
      for (var r = 0; r < gridtotal; r++) {
        tempArr.push(Math.floor((Math.random() * 2)) ? 'red' : 'white');
      }
    this.setState({
      currentData: tempArr
    });
    console.log(this.state.currentData);
   },

  run: function() {
   if (this.state.pausestatus === 0){ 
      this.setState({
        gameStatus: setInterval(this.switchColors, this.state.runRate)
      });
    this.updateGeneration();
    }
    },

   getNewGeneration: function() { 
     if(this.state.pausestatus === 0){
       this.setState({
          generation: (this.state.generation + 1)
      });
     }else{this.setState({
         generation: this.state.generation
       });}
      },

    updateGeneration: function() { 
     this.setState({
         generation: setInterval(this.getNewGeneration, this.state.runRate)
       });
     },

   clearAll: function() {
    var emptyarray = [];
    this.pauseAction();
    this.setState({
          currentData: emptyarray
          });
     this.setState({
          generation: 0
          });
   },

   speedUp: function() {
      this.setState({
        runRate: (this.state.runRate - 500)
      })

  },

  slowDown: function() {
        this.setState({
          runRate: (this.state.runRate + 1000)
       })
    },


   pauseAction: function() { 
    if(this.state.pausestatus === 0){
      this.setState({
        pausestatus: 1
        });
      this.setState({
        pausebutton: 'Start'
      });
    }else{this.setState({
        pausestatus: 0
      });
      this.setState({
        pausebutton: 'Pause'
      });
          }
   },


  render: function() {
   var tempgrid = [],
      tempgridtotal2 = this.state.totalColumns * this.state.totalRows;
       for (var x = 0; x < tempgridtotal2; x++) {
         tempgrid.push(<ActionBox divkey={x} divcolor={this.state.currentData[x]}/>);
       }
    return (
     <div>
     <div>
         Generation: {this.state.generation}
       </div>
       <div>
         <button type="button" className="normalBtn" id="btn1" onClick={this.pauseAction} style={{backgroundColor:this.state.bgColor}} >{this.state.pausebutton}</button>
         <button type="button" className="normalBtn" id="btn1" onClick={this.clearAll} style={{backgroundColor:this.state.bgColor}}>Clear</button>
         <button type="button" className="normalBtn" id="btn1" onClick={this.speedUp} style={{backgroundColor:this.state.bgColor}}>Faster</button>
         <button type="button" className="normalBtn" id="btn1" onClick={this.slowDown} style={{backgroundColor:this.state.bgColor}}>Slower</button>
       </div>
     <div id="applicationGrid">
         {tempgrid} 
     </div>
       </div>
   );
  }
 });

var ActionBox = React.createClass({ 
    render: function() {
      return(
        <div id="actionBox" Name={this.props.divkey}  style={{backgroundColor:this.props.divcolor}} >
        </div>
      );
     },
  });

  var MyApp = React.createClass({  

      getInitialState: function() {
            return {
                seed: 'default'
              }  
         },

       render: function() {
        return(
          <div id="mainDiv" >
          <h1> Game of Life! </h1>
          <ButtonsAndGrid /> <Footer />
          </div>
        );
       }, 
      });

    var Footer = React.createClass({
       render() {
           return (
              <footer>
                 <div id="containerfooter">
                  <p>Written by <a href="http://codepen.io/profaneVoodoo/full/dXBJzN/">John Gillespie</a> for   FreeCodeCamp Campers (and also to impress my kids). Happy Coding!</p>
                 </div>
              </footer>
              );
            }
        });

 ReactDOM.render(
   <MyApp />  ,
document.getElementById('GoL')
 );

#2

I think I see the problem:

When you update state, it tells React to re-render, but nothing more. So this.state.runRate is updating, but your setInterval function called in updateGeneration will happily continue to use the old value forever. You need to update it manually. Note too that you should clearInterval before setting a new one.