React JS When and where to properly update a state value used in a loop

React JS When and where to properly update a state value used in a loop
0

#1

The approach I’m taking for the Game of Life uses a grid of divs created with a loop in the component called ApplicationGrid.

Each div is given a “key” with an initial state of zero.

After each div is created, I need the “key” iterated by one so that all the divs have a unique value.

I have written the function called updateKey() to set the new state for key.

When and where should I call the updateKey() function? If I add it to the statement in the loop right after the new div gets pushed to rows[], all of the divs have a key of “3463”! So I am obviously not doing something correctly.

The CodePen for this is here

var ActionBox = React.createClass({ 

  getInitialState: function() {
    return {
      bgColor2: 'white',
      generation: 0
    }  
  },

  handleClick2: function() {
   if(this.state.bgColor2 === 'white')
    {this.setState({
      bgColor2: 'pink',
      generation: 1
   })
    console.log("My generation is one.")
    }else{
      this.setState({
      bgColor2: 'white',
      generation: 0
    })
      console.log("My generation is zero.")
    }
  },

 render: function() {
   var test = this.props.myColumnNumber;
    return(
      <div id="actionBox" onClick={this.handleClick2} style={{backgroundColor:this.state.bgColor2}}>
        </div>
    );
  }, 
});


 var ApplicationGrid = React.createClass({  

     getInitialState: function() {
      return {
        key: 0
       }  
    },


  updateKey: function() {
 
    this.setState({
      key: (this.state.key+1)
    })  
  },

 render: function() {
     var row = [];
  for(var j=0; j<30; j++){
     for(var i=0; i<30; i++){
        row.push(<ActionBox myRowNumber={j} myColumnNumber={i} pears = {this.props.oranges} divkey={this.state.key}/>);
    this.updateKey();
}

   }
   return(
     <div id="applicationGrid">
      {row}
        </div>
    );
  }, 

});

var ButtonsAndGrid = React.createClass({ 

  getInitialState: function() {
   return {
      bgColor: 'white'
    }  
  },

  handleClick: function() {
    //this.props.plethora()
    this.setState({
      bgColor: 'blue'
    })
    this.liveOrDie();
  },

  liveOrDie: function() {
     console.log("The generation of cell 0,0 is ...")
  },

  render: function() {

   return(
    <div>
    <div id="buttonsDiv">
  
       <button type="button" ref="button1" className="normalBtn" id="btn1" onClick={this.handleClick} style=    {{backgroundColor:this.state.bgColor}}>Live or Die</button>
  
      </div>
    <ApplicationGrid oranges = {this.props.apples} />
    </div>
    );
  }, 
});

var MyApp = React.createClass({  

  getInitialState: function() {

    return {
     lifeordeath: 0
   };
  },    

  render: function() {
  return(
     <div id="mainDiv" >
  <h1> Game of Life! </h1>
    <ButtonsAndGrid apples={this.state.lifeordeath} /> <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

If you’re using the key prop to ensure that the cells are unique (which what’s intended for from what I remember, my React is getting rusty), I’m not sure why you need to set this through the state of the parent.

Just assign key = {i + j*10}, that should be enough.


#3

you have used updatekey() which is changing the state,in render function,so after each update it will re-render which will go in an infinite loop.So never use anything which is changing state in render function


#4

OK I used a variation of that approach and got it to do exactly what I wanted.

If interested, see the updated CodePen

Thanks!