7

I'm making this Conway's game of life react project and it was working just fine but when I added the last couple of buttons to clear the board and some other functionalities react gave me this error

Maximum update depth exceeded. This can happen when a component 
repeatedly calls setState inside componentWillUpdate or 
componentDidUpdate. React limits the number of nested updates to 
prevent infinite loops. 

From the code snippets it's been showing me it seems that the clear() function is the problem here, but I don't think I did set state inside a render() to trigger an infinite loop. Here are all the code for the clear and componentDidMount, I don't have a componentWillUpdate or componentDidUpdate in my app.

the clear() and Play function in the main class

EDIT 1 : It's telling me that there's something wrong with the setState inside the play() function, however, I always implemented the play function this way and it was always working since the beginning....

clear = ()=>{
    var g = Array(this.rows).fill().map(()=> Array(this.cols).fill(false));

    this.setState({
        generations:0,
        fullGrid: g
    })
}

.....

play = () => {

    let g1 = this.state.fullGrid;
    let g2 = arrayClone(this.state.fullGrid);

    for (let i = 0; i < this.rows; i++) {
        for (let j = 0; j < this.cols; j++) {
            let count = 0;

            if (i > 0)
                if (g1[i - 1][j]) count++;
            if (i > 0 && j > 0)
                if (g1[i - 1][j - 1]) count++;
            if (i > 0 && j < this.cols - 1)
                if (g1[i - 1][j + 1]) count++;
            if (j < this.cols - 1)
                if (g1[i][j + 1]) count++;
            if (j > 0)
                if (g1[i][j - 1]) count++;
            if (i < this.rows - 1)
                if (g1[i + 1][j]) count++;
            if (i < this.rows - 1 && j > 0)
                if (g1[i + 1][j - 1]) count++;
            if (i < this.rows - 1 && this.cols - 1)
                if (g1[i + 1][j + 1]) count++;
            if (g1[i][j] && (count < 2 || count > 3)) g2[i][j] = false;
            if (!g1[i][j] && count === 3) g2[i][j] = true;
        }
    }

    this.setState({
        fullGrid: g2,
        generations: this.state.generations + 1
    });

}


playButton = ()=>{
    clearInterval(this.intervalId);
    this.intervalId = setInterval(this.play, this.speed);
}

pauseButton = ()=>{
    clearInterval(this.intervalId);
}

slow = ()=>{
    this.speed = 1000;
    this.playButton();
}

fast = ()=>{
    this.speed = 100;
    this.playButton();
}

clear = ()=>{
    var g = Array(this.rows).fill().map(()=> Array(this.cols).fill(false))

    this.setState({
        generations:0,
        fullGrid: g
    })
}

The Button Class

class Buttons extends React.Component{

handleSelect = (evt) =>{
    this.props.gridSize(evt);
}

render(){
    return (
        <div className="center">
            <ButtonToolbar>
                <button className='btn btn-info'  onClick={this.props.playButton}>
                    PLAY
                </button>
                <button className='btn btn-info'  onClick={this.props.pauseButton}>
                    PAUSE
                </button>
                <button className='btn btn-info'  onClick={this.props.clear}>
                    CLEAR
                </button>
                <button className='btn btn-info'  onClick={this.props.slow}>
                    SLOW
                </button>
                <button className='btn btn-info'  onClick={this.props.fast}>
                    FAST
                </button>
                <button className='btn btn-info'  onClick={this.props.seed}>
                    SEED
                </button>
                <DropdownButton
                    title="Grid Size"
                    id="size-menu"
                    onSelect={this.handleSelect}
                >
                    <MenuItem eventKey="1">20x10</MenuItem>
                    <MenuItem eventKey="2">50x30</MenuItem>
                    <MenuItem eventKey="3">70x50</MenuItem>
                </DropdownButton>
            </ButtonToolbar>
        </div>
    )
}

}

UWGOOSE
  • 833
  • 3
  • 11
  • 20
  • can you add the code for your functions in the buttons. `seed,clear,fast,slow,pauseButton,playButton` – Omar Mar 11 '18 at 16:38
  • for sure, added :) – UWGOOSE Mar 11 '18 at 16:49
  • dont you need to do `onClick={() => this.props.fast())` ? To actually execute the function. – Omar Mar 11 '18 at 16:54
  • oh for the `onClick` methods in the buttons are all changed to that format now. I didn't update the code in the question. But I have narrowed it down to the clear and seed method. Because when i comment those out the code works fine. – UWGOOSE Mar 11 '18 at 17:17

1 Answers1

6

Your onClick handlers are being called continuously. Change them to functions that return the function you wish to call and this should fix your issue.

Example:

<button className='btn btn-info'  onClick={() => this.props.playButton}>
    PLAY
</button>
Sean
  • 2,609
  • 1
  • 18
  • 34
  • Thanks for answering but unfortunately it still shows the same error. :( – UWGOOSE Mar 11 '18 at 16:17
  • 1
    Did you make this change for all the functions? I only used the `playButton` one as an example – Sean Mar 11 '18 at 16:17
  • yes , I changed all of them and recompiled the app but it still shows the same error :( – UWGOOSE Mar 11 '18 at 16:18
  • try remove the function calls one at a time and running the app to see if we can work out which one is throwing it – Sean Mar 11 '18 at 16:19
  • Hey so i commented out the clear and seed method and now the code compiles but only the pause button or any button doesn't really work, and there were no blocks showing up on the grid either... – UWGOOSE Mar 11 '18 at 17:23
  • I don't think you have included your seed method above? – Sean Mar 11 '18 at 18:17