繁体   English   中英

为什么 setState() 不更新 React 上的渲染?

[英]Why setState() doesn't update render on React?

我正在尝试制作一个由“单元格”组成的 2D 游戏板,它具有一个名为isAlive的二进制状态值。 用户可以通过单击它们来更改此值。 该值使用不同的颜色向用户指示。 Board.js构造函数使用false值创建每个单元格。 该板还有一个“重置”按钮,用于将所有 Cell 重置为false

当我单击它们时,单元格的值会正确更改。 单击“重置”按钮时,我希望每个 Cell 的isAlive值为false 但是,当视觉上按下“重置”按钮时,板上没有任何变化(单元格的颜色不会改变)。 console.log(this.state.cells); Board.js上的handleClick()方法上的Board.js所有单元打印props: Object { isAlive: false } 那么为什么 Cell 没有在视觉上更新呢? 我在这里做错了什么?

Board.js

export default class Board extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            cells: []
        };
        this.rowNum = 10;
        this.colNum = 10;

        for (let i = 0; i < (this.rowNum * this.colNum); i++) {
            this.state.cells.push(<Cell isAlive={false}/>);
        }
        this.handleClick = this.handleClick.bind(this);
        this.getCols = this.getCols.bind(this);

    }

    getCols() {
        let cols = [];
        for (let i = this.rowNum; i <= (this.rowNum * this.colNum); i += this.rowNum) {
            cols.push(this.state.cells.slice(i - this.rowNum, i).map(function (item, i) {
                return <div key={i}>{item}</div>
            }));
        }
        return cols;
    }

    handleClick() {
        const newBoard = this.state.cells;
        newBoard.forEach((item, index, arr) => {
            arr[index] = <Cell isAlive={false}/>
        });
        this.setState({
                cells: newBoard
            }, function () {
                console.log(this.state.cells);
            }
        );
    }

    render() {
        return (<div className="background">
                <table className="gameBoard">
                    <tbody>
                    <tr>
                        {this.getCols().map(function (item, index) {
                            return <td className="col" key={index}>{item}</td>
                        })}
                    </tr>
                    </tbody>
                </table>
                <button onClick={this.handleClick}> Reset</button>
            </div>
        );
    }

}

Cell.js 的重要部分:

export default class Cell extends React.Component {
    constructor(props) {
        super(props);
        this.colors = {
            dead: '#041b40',
            alive: '#b2e8f7',
            hover_dead: '#495d76',
            hover_alive: '#e6fffd'
        };

        this.state = {
            isAlive: this.props.isAlive,
            isMouseDown: false,
            isHovering: false
        };


        this.handleClick = this.handleClick.bind(this)
    }

    handleClick() {
        this.setState({
            isAlive: !this.state.isAlive,
            isMouseDown: this.state.isMouseDown,
            isHovering: this.state.isHovering

        })
    }

    ...

    determineColor() {
        if (this.state.isAlive && this.state.isHovering) {
            return this.colors.hover_alive;
        } else if (!this.state.isAlive && this.state.isHovering) {
            return this.colors.hover_dead;
        } else if (this.state.isAlive && !this.state.isHovering) {
            return this.colors.alive;
        }else {
            return this.colors.dead;
        }
    }

    render() {
        return (
            <div>
                <button className='square'
                        onClick={this.handleClick}
                        type='button'
                        style={{
                            backgroundColor: this.determineColor()
                        }}>
                </button>
            </div>
        )
    };


}

您需要在道具更改时更新内部状态:

export default class Cell extends React.Component {
    constructor(props) {
        super(props);
        this.colors = {
            dead: '#041b40',
            alive: '#b2e8f7',
            hover_dead: '#495d76',
            hover_alive: '#e6fffd'
        };

        this.state = {
            isAlive: this.props.isAlive,
            isMouseDown: false,
            isHovering: false
        };


        this.handleClick = this.handleClick.bind(this)
    }
    componentDidUpdate(prevProps, prevState) { //<--HERE
       this.setState({isAlive: this.props.isAlive})
    }
    handleClick() {
        this.setState({
            isAlive: !this.state.isAlive,
            isMouseDown: this.state.isMouseDown,
            isHovering: this.state.isHovering

        })
    }

    ...

    determineColor() {
        if (this.state.isAlive && this.state.isHovering) {
            return this.colors.hover_alive;
        } else if (!this.state.isAlive && this.state.isHovering) {
            return this.colors.hover_dead;
        } else if (this.state.isAlive && !this.state.isHovering) {
            return this.colors.alive;
        }else {
            return this.colors.dead;
        }
    }

    render() {
        return (
            <div>
                <button className='square'
                        onClick={this.handleClick}
                        type='button'
                        style={{
                            backgroundColor: this.determineColor()
                        }}>
                </button>
            </div>
        )
    };

您必须使用 componentDidUpdate

 componentDidUpdate(prevProps) {
    
      if (this.props.isAlive!== prevProps.isAlive) {
      this.setState({isAlive: this.props.isAlive})
      }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM