教程:React 简介 - 重新渲染整个集合而不是最近更改的元素

Tutorial: Intro to React - Rerendering the whole collection instead of the most recently changed element

我一直在通过官方“Tutorial: Intro to React

完整代码可见here

提供了九个方格的棋盘。方块的状态 "lifted up" 进入游戏 class 以最小化有状态组件的数量。单击方块将更改所述游戏 class 中的状态。我观察到的是,现在每个方块都被重新渲染,而不仅仅是我点击的那个。

为了把握问题我统计了Square功能组件的return-函数的调用次数

有问题的代码行:

import React, {Component} from 'react'

function Square(props) {
    return (
        <button className="square" onClick={props.onClick}>
            {props.value}
        </button>
    );
}

class Board extends React.Component {
    renderSquare(i) {
        return (
            <Square
                value={this.props.squares[i]}
                onClick={() => this.props.onClick(i)}
            />
        );
    }

    render() {
        return (
            <div>
                <div className="board-row">
                    {this.renderSquare(0)}
                    {this.renderSquare(1)}
                    {this.renderSquare(2)}
                </div>
                <div className="board-row">
                    {this.renderSquare(3)}
                    {this.renderSquare(4)}
                    {this.renderSquare(5)}
                </div>
                <div className="board-row">
                    {this.renderSquare(6)}
                    {this.renderSquare(7)}
                    {this.renderSquare(8)}
                </div>
            </div>
        );
    }
}

export default class Game extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            squares: Array(9).fill(null),
            xIsNext: true,
        };
    }

    handleClick(i) {
        const squares = this.state.squares.slice();
        squares[i] = this.state.xIsNext ? "X" : "O";
        this.setState({
            squares: squares,
            xIsNext: !this.state.xIsNext,
        });
    }

    render() {
        const squares = this.state.squares

        return (
            <div className="game">
                <div className="game-board">
                    <Board
                        squares={squares}
                        onClick={i => this.handleClick(i)}
                    />
                </div>
            </div>
        );
    }
}

index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import Game from './Game';

ReactDOM.render(<Game />, document.getElementById('react'));

我预计 React 只会重新渲染我点击的方块。

取而代之的是,在每次点击任意一个空闲方块后,所有九个方块都会重新呈现。

根据我对 React 的理解,其中一个有益的特性是虚拟 DOM,它能够决定哪些节点需要在 "real" DOM 上更新。 'state' 的全部目的不就是计算必须重新渲染屏幕的哪一部分吗?

我意识到当我改变 "Game" 的状态时,整个 "game component" 将被重新渲染。但这不正是应该避免的吗?如何最大限度地减少有状态组件的数量并保持良好的性能?在这种情况下,它只有 9 个方块重新渲染。但是想象一下我有一个 200x200 正方形的区域...

尝试使用 shouldComponentUpdate

实现 Square
class Square extends React.Component {
  shouldComponentUpdate(nextProps) {
    return this.props.value !== nextProps.value;
  }

  render() {
    const { value, onClick } = this.props;

    return (
      <button className="square" onClick={onClick}>
        {value}
      </button>
    );
  }
}