web-dev-qa-db-ja.com

最大更新深度を超えました。これは、コンポーネントがcomponentWillUpdateまたはcomponentDidUpdate内で繰り返しsetStateを呼び出すときに発生する可能性があります。

私はこのコンウェイのライフゲームの反応プロジェクトを作成していますが、うまく機能していましたが、ボードをクリアするために最後のいくつかのボタンを追加すると、他のいくつかの機能が反応してこのエラーが発生しました

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. 

コードスニペットから、ここではclear()関数が問題であるように見えますが、render()内で状態を設定して無限ループをトリガーしたとは思いません。クリアとcomponentDidMountのすべてのコードを以下に示します。アプリにcomponentWillUpdateまたはcomponentDidUpdateがありません。

メインクラスのclear()およびPlay関数

編集1:play()関数内のsetStateに問題があることを伝えていますが、私は常に再生関数をこの方法で実装し、最初から常に機能していました。

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
    })
}

ボタンクラス

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>
    )
}

}

5
UWGOOSE

onClickハンドラーが継続的に呼び出されています。呼び出したい関数を返す関数に変更すると、問題が解決します。

例:

<button className='btn btn-info'  onClick={() => this.props.playButton}>
    PLAY
</button>
6
Sean