代码之家  ›  专栏  ›  技术社区  ›  Koray Tugay

React组件在return中访问状态时未更新?

  •  0
  • Koray Tugay  · 技术社区  · 5 年前

    我是新手。。

    我在跟踪 Official React Tutorial .以下代码是教程中所示的工作版本:

    class Square extends React.Component {
    
        constructor(props, context) {
            super(props, context);
        }
    
        render() {
            return (
                <button className="square"
                        onClick={() => this.props.onClick()}>
                    {this.props.value}
                </button>
            );
        }
    }
    
    class Board extends React.Component {
    
        constructor(props, context) {
            super(props, context);
            this.state = {
                squares: Array(9).fill(null)
            };
        }
    
        renderSquare(i) {
            return (
                <Square
                    value={this.state.squares[i]}
                    onClick={() => this.handleClick(i)}
                />
            );
        }
    
        render() {
            const status = 'Next player: X';
    
            return (
                <div>
                    <div className="status">{status}</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>
            );
        }
    
        handleClick(i) {
            this.setState(
                () => {
                    const squares = this.state.squares.slice();
                    squares[i] = 'X';
                    this.setState({squares: squares});
                }
            );
        }
    }
    

    总而言之, Board 渲染9 Squares 并将回调函数传递给 Square ,更新了 state 关于 .

    上面的代码运行得很好,当我点击 广场 s、 其值更新为 X .

    然而,我在遵循教程的过程中犯了一个错误,并实际实现了 render renderSquare 方法 BoardComponent 详情如下:

    renderSquare(i) {
        return (
            <Square
                value={i}
                onClick={() => this.handleClick(i)}
            />
        );
    }
    
    render() {
        const status = 'Next player: X';
    
        return (
            <div>
                <div className="status">{status}</div>
                <div className="board-row">
                    {this.renderSquare(this.state.squares[0])}
                    {this.renderSquare(this.state.squares[1])}
                    {this.renderSquare(this.state.squares[2])}
                </div>
                <div className="board-row">
                    {this.renderSquare(this.state.squares[3])}
                    {this.renderSquare(this.state.squares[4])}
                    {this.renderSquare(this.state.squares[5])}
                </div>
                <div className="board-row">
                    {this.renderSquare(this.state.squares[6])}
                    {this.renderSquare(this.state.squares[7])}
                    {this.renderSquare(this.state.squares[8])}
                </div>
            </div>
        );
    }
    

    变化就在眼前 Board#renderSquare 方法以及如何从 Board#render .

    这一变化破坏了产品的功能和价值 广场 正在单击的不会得到更新。

    在我看来,这两种实现之间应该没有任何区别,但很明显我遗漏了一些东西。为什么要搬家 this.state.squares[] 提供 方法破坏功能?

    1 回复  |  直到 5 年前
        1
  •  0
  •   Federkun    5 年前

    问题是 this.state.squares[n] 可以是 null X .

    在代码中,可以执行以下操作:

    renderSquare(i) {
        return (
            <Square
                value={i}
                onClick={() => this.handleClick(i)}
            />
        );
    }
    
    
    
    {this.renderSquare(this.state.squares[n])}
    

    你转到 renderSquare 这个 价值 ,而不是索引。 i 在里面 renderSquare 无效的 十、 .这是什么意思 handleClick 不知道要更改什么,因为它需要一个索引。

        2
  •  0
  •   Dennis Vash    5 年前

    问题出在政府内部 renderSquare(i) .

    在…上 this.renderSquare(this.state.squares[0]) 你路过吗 null renderSquare 方法

    为了重新加载组件,您需要定义一个与前一个不同的新状态,但是:

      handleClick(i) {
        this.setState(() => {
          const squares = [...this.state.squares];
          squares[i] = "X";                      //  <-- i is null
          this.setState(prevState => {
            const newState = { squares: squares };
            console.log(prevState);
            console.log(newState);
            console.log(prevState === newState);  // <-- true so no rerender. 
            return newState;
          });
        });
      }
    

    要修复它,请定义 state.squares constructor

      constructor(props, context) {
        super(props, context);
        this.state = {
          squares: [...Array(9)].map((_, i) => i)
        };
      }
    
      renderSquare(i) {
        return <Square value={i} onClick={() => this.handleClick(i)} />;
      }
    

    查看下面的示例: codesandbox .