为什么我的React的组件点击方法在渲染时触发?

I am rewriting ReactJS's "starter game" in ES6 with arrow functions (to remove the use of .bind(), class properties and typescript.

Apparently in my code handleSquareClick is triggered at rendering time, setState is hence executed, resulting in error

错误:已超过最大更新深度。当组件重复调用componentWillUpdate或componentDidUpdate内部的setState时,可能会发生这种情况。 React限制了嵌套更新的数量,以防止无限循环。

为什么?

Game.tsx:

import React, { PureComponent } from 'react';
import Board from "../Board";

type State = {
    history:
        {
            squares: Array<number>
        }[];
    currentStep: number;
    xIsNext: boolean;
};

class Game extends PureComponent {

    state: State = {


        history: [{
            squares: Array(9).fill(null)
        }],


        currentStep: 0,


        xIsNext: true
    };

    calculateWinner(squares: Array<number>) {


        const lines = [
            [0, 1, 2],
            [3, 4, 5],
            [6, 7, 8],
            [0, 3, 6],
            [1, 4, 7],
            [2, 5, 8],
            [0, 4, 8],
            [2, 4, 6]
        ];


        for (let i = 0; i < lines.length; i++) {


            const [a, b, c] = lines[i];


            if (squares[a] !== null && squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
                return squares[a];
            }
        }
        return null;

    }

    handleSquareClick = (i: any) => {
        console.log(i);

        // ...more code here

        this.setState({
           history: [...historyClone, { squares }],
           currentStep: historyClone.length,
           xIsNext: !xIsNext
        });

    };


    render() {
        const { history, currentStep } = this.state;

        const current = history[currentStep];

        return (
            <div>
                {  }
                <Board
                    squares={current.squares}
                    handleSquareClick={this.handleSquareClick}

            <
        );
    }

}

export default Game;

Board.tsx

import React, { PureComponent } from 'react';
import Board from "../Board"

type State = {
    history:
        {
            squares: Array<number>
        }[];
    currentStep: number;
    xIsNext: boolean;
};

class Game extends PureComponent {
    state: State = {


        history: [{
            squares: Array(9).fill(null)
        }],


        currentStep: 0,


        xIsNext: true
    };

    calculateWinner(squares: Array<number>) {

        const lines = [
            [0, 1, 2],
            [3, 4, 5],
            [6, 7, 8],
            [0, 3, 6],
            [1, 4, 7],
            [2, 5, 8],
            [0, 4, 8],
            [2, 4, 6]
        ];


        for (let i = 0; i < lines.length; i++) {


            const [a, b, c] = lines[i];


            if (squares[a] !== null && squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
                return squares[a];
            }
        }
        return null;

    }

    handleSquareClick = (i: any) => {
        console.log(i);

        this.setState({
            history: [...historyClone, { squares }],
            currentStep: historyClone.length,
            xIsNext: !xIsNext
        });
    };


    render() {
        const { history, currentStep } = this.state;

        const current = history[currentStep];

        return (
            <div>
                <Board
                    squares={current.squares}
                    handleSquareClick={this.handleSquareClick}
            <
        );
    }

}

export default Game;