Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate

24,064

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>
Share:
24,064
UWGOOSE
Author by

UWGOOSE

Updated on March 12, 2020

Comments

  • UWGOOSE
    UWGOOSE about 4 years

    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
    UWGOOSE about 6 years
    Thanks for answering but unfortunately it still shows the same error. :(
  • Sean
    Sean about 6 years
    Did you make this change for all the functions? I only used the playButton one as an example
  • UWGOOSE
    UWGOOSE about 6 years
    yes , I changed all of them and recompiled the app but it still shows the same error :(
  • Sean
    Sean about 6 years
    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
  • UWGOOSE
    UWGOOSE about 6 years
    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...
  • Sean
    Sean about 6 years
    I don't think you have included your seed method above?