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

时间:2020-05-08 21:51:27

标签: reactjs

我正在ES6中用箭头函数重写ReactJS的"starter game"(以消除对.bind(),类属性和打字稿的使用。

很明显,我的代码handleSquareClick是在渲染时触发的,因此执行了setState,从而导致错误

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

为什么

Game.tsx

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

class Game extends PureComponent {

    state = {

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

        currentStep: 0,

        xIsNext: true
    };


    handleSquareClick = (i) => {
        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 {
    Title,
    Square
} from './styles';

class Board extends PureComponent {

    getSquareStringValue(value) {
        if (value === 0) return 'X';
        else if (value === 1) return 'O';
        else return '';
    }

    renderSquare(props) {
        const { key, value } = props;

        return (
            <Square
                    key={key}
                    className="square"
                    onClick={this.props.handleSquareClick(value)}>
                { this.getSquareStringValue(value) }
            </Square>
        )
    }

    render() {
        const { title, squares } = this.props;

        return (
            <div className="board">
                <Title>{title}</Title>
                <div>
                    {[...Array(3).keys()]
                        .map((i) => (
                            <div className="board-row" key={i}>
                                {[...Array(3).keys()]
                                    .map((j) => this.renderSquare({
                                        key: (i+1)*(j+1),
                                        value: squares[i]
                                    }))
                                }
                            </div>
                        ))
                    }
                </div>
            </div>
        )
    }

    static defaultProps = {
        title: "Board",
    };
}



export default Board;

Board / styles.ts

import styled from 'styled-components';

export const Title = styled.h1`
    font-size: 1rem;
`;


export const Square = styled.div`
    height: 16px;
    width: 16px;
    border: 1px solid #000;
    display: inline-block;
`;

1 个答案:

答案 0 :(得分:2)

您只需要更改以下内容即可:

onClick={this.props.handleSquareClick(value)}>

对此:

onClick={()=> this.props.handleSquareClick(value)}>

因为onClick期望函数作为值,但是您正在做的是调用此函数。

我们知道,如果将()放在函数的末尾,则会调用该函数。因此,我更改的是通过使用() => ...箭头函数来传递函数而不调用它。