coderHook coderHook - 2 months ago 15
React JSX Question

Problems with performance on Game Of life (React.js + Redux)

I am experiencing some problems when my Game Of Life run by itself. To do so I am trying to set a setInterval and trigger the function that now is triggered each time someone clicks on Next. But it is causing me a lot of problems.

The main problem is that when I set a setInterval( () => this.handleChange(), 100) the movement of the game is really slow and it finally crash in codepen.

class Board extends React.Component{

handleChange(){ [.........] //just to indicate that here is more code that is not showing and dont think it is important to the question.

nextMovement() [...........]

render(){
var createBoard = this.props.board.map((idx) => {

return <Cell
onClick={() => this.props.toggleAlive(idx.index)}
key = {idx.index}
index = {idx.index}
col = {idx.col}
row = {idx.row}
val = {idx.val}
/>
});

return(

<div className="board">
{createBoard}
<button className="btn btn-danger" onClick={()=>this.handleChange()}>Next</button>
{setInterval(() => this.handleChange(), 100)}
</div>
);
}
}


/* - - - Reducers - - - */


Here you can find my codePen as well to see the full code.

http://codepen.io/DiazPedroAbel/pen/bwNQAJ

I was also looking at this question on stackOverFlow, who seems to have the same problem as me, but finally to solve it he started using canvas.

I am also wondering if the low performance of my game is due to the way I create the next board. I just have two boards, the actual one and the next one which contains all the new movement, and when I finally fill up this newBoard I change the board on the state triggering an action. Or Maybe the problem is that I am doing something wrong with the setInterval function.

Thanks in advance, any help would be appreciate.

DDS DDS
Answer

To fix your issue you should add

shouldComponentUpdate(next) {
  let props=this.props; 
  return props.col!==next.col || props.row !== next.row || props.val!==next. val;
}

to your Cell class. This will make sure only changed cells get rerendered.

Redux is normally pretty good at optimizing this stuff but there are two problems with your setup for this to work:

  • Your Cell class isn't connected. This means Redux can't help control its rendering. If you wanted that then pass the row/col in as the props but have it get its val from Redux in mapStateToProps.
  • You update the board by replacing. This can work as long as the cells in the new board that have not changed reference the same objects as the old board. This is how Redux checks if cells have changed. So when copying the old board make sure it's a shallow copy, and then when updating cells, replace the old cell object with an entirely new object. Remember: you're not allowed to modify objects that are in the Redux state. But you can modify the array itself because it's a copy and this means you can replace cells without modifying the original cell. If your cells in Redux only contain numbers, then you don't have to worry about it since with Numbers the value is the identity. This means if you write in the same value Redux will see it's the same. Redux cannot check that two different objects have the exact same properties because it takes too long.

Using the shouldComponentUpdate above makes it not necessary to do these things but you should probably will do them because it's the a Redux Way. Without these changes you're not using Redux well. In fact you lose almost all of Redux-React's benefits.

Either way will make your board fast however, provided that only a limited potion of the board actually changes. If the whole board is flickering then there's nothing you can do except use a different technology, such as Canvas or React-Canvas. DOM is slow.