简体   繁体   English

在父状态更改时渲染子组件

[英]Render child component on parent state change

Full React code. 完整的React代码

  class Square extends React.Component{
    render(){
      const letters = this.props.print;
      const print = letters === 0 ? "" : letters;

      return(
        <div>
          <button className='boxes' onClick={this.props.onClick}>
            {print}
          </button>
        </div>        
      );
    }   
  }


  class Game extends React.Component{
    constructor(props){
      super(props);
      this.handleClick = this.handleClick.bind(this);
      this.state = {
        letter: 'O',
        gameWon: false,
        letterArr: [0,0,0,0,0,0,0,0,0],
        winArr: [
         'X,X,X,0,0,0,0,0,0',
         '0,0,0,X,X,X,0,0,0',
         '0,0,0,0,0,0,X,X,X',
         'X,0,0,X,0,0,X,0,0',
         '0,X,0,0,X,0,0,X,0',
         '0,0,X,0,0,X,0,0,X',
         'X,0,0,0,X,0,0,0,X',
         '0,0,X,0,X,0,X,0,0',
         'O,O,O,0,0,0,0,0,0',
         '0,0,0,O,O,O,0,0,0',
         '0,0,0,0,0,0,O,O,O',
         'O,0,0,O,0,0,O,0,0',
         '0,O,0,0,O,0,0,O,0',
         '0,0,O,0,0,O,0,0,O',
         'O,0,0,0,O,0,0,0,O',
         '0,0,O,0,O,0,O,0,0'
        ]
      };
    }
    componentDidUpdate(){
      let o_s = this.state.letterArr.map((o) => {return o == 'X' ? 0 : o}).toString();
      let x_x = this.state.letterArr.map((x) => {return x == 'O' ? 0 : x}).toString();
      let oWin = (this.state.winArr.indexOf(o_s) != -1);
      let xWin = (this.state.winArr.indexOf(x_x) != -1);
      if( oWin == true ){
        console.log("O WINS!!!");
        board(gameVar.mode, gameVar.letter);
      }else if( xWin == true ){
        console.log("X WINS!!!");
        board(gameVar.mode, gameVar.letter);
      }
    }

    handleClick(i){
      let letter = this.state.letter;
      let arr = this.state.letterArr.slice();
      let change = this.state.letter == "O" ? "X" : "O";
      arr[i] = letter;
      this.setState({letter: change});
      this.setState({letterArr: arr});
    }

    squares(i){
      if(this.state.letterArr[i] == 0){
        return(
          <Square 
            print={this.state.letterArr[i]} 
            onClick={() => {this.handleClick(i)}} 
          />
        );
      }else{
        return(
          <Square
            print={this.state.letterArr[i]}
          />
        );
      }
    }

    render(){
      return(
        <div className='justify'>
          {this.squares(0)}
          {this.squares(1)}
          {this.squares(2)}
          {this.squares(3)}
          {this.squares(4)}
          {this.squares(5)}
          {this.squares(6)}
          {this.squares(7)}
          {this.squares(8)}
        </div>
      );
    }
  }

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

My issue is handleClick updates the constructor and then componentDidUpdate fires, calling Board() . 我的问题是handleClick更新构造函数,然后激发componentDidUpdate,调用Board() I was expecting setState inside handleClick to re-render my class Box first. 我期望handleClick setState首先重新渲染我的类Box

  1. Why is setState not calling render? 为什么setState不调用render?
  2. How can I call board() after Box updates with new props? 使用新道具更新Box后如何调用board()

Link to full code: https://codepen.io/xcidis/pen/qVPoME?editors=0011 链接到完整代码: https : //codepen.io/xcidis/pen/qVPoME?editors=0011

There are a number of problems with your code. 您的代码有很多问题。 In the render method on your Game component you are calling the method Box() , but that method does not return any value. Game组件上的render方法中,您正在调用Box()方法,但是该方法不返回任何值。 Even if it did you would need to make some changes since I assume you want multiple boxes to render. 即使这样做,您也需要进行一些更改,因为我假设您要渲染多个框。 Also the Box() method on your Game component doesn't take any value as an argument, but you are calling it with a number. 同样, Game组件上的Box()方法不将任何值用作参数,而是使用数字来调用它。

In your Box component you are extracting the const num from the property print , but print is not passed to the component from the Game component. Box组件中,您将从属性print提取const num ,但是print不会从Game组件传递到该组件。

There are a bunch of other problems as well... I suppose this isn't the complete code so didn't bother writing up all the issues. 还有很多其他问题...我想这不是完整的代码,因此不必费心写下所有问题。

componentDidUpdate(){
      let o_s = this.state.letterArr.map((o) => {return o == 'X' ? 0 : o}).toString();
      let x_x = this.state.letterArr.map((x) => {return x == 'O' ? 0 : x}).toString();
      let oWin = (this.state.winArr.indexOf(o_s) != -1);
      let xWin = (this.state.winArr.indexOf(x_x) != -1);
      if( oWin == true ){
        //confetti();
        setTimeout(function(){
          alert('O WINN!!!')
          board(gameVar.mode, gameVar.letter)
        }, 3000);
      }else if( xWin == true ){
        //confetti();
        setTimeout(function(){
          alert('X WINS!!!')
          board(gameVar.mode, gameVar.letter)
        }, 3000);
      }
    }

Apparently setState and componentDidUpdate are asynchronous. 显然setStatecomponentDidUpdate是异步的。 I used setTimeout to pause setState -> componentDidUpdate firing before my component rendered. 我使用setTimeout在呈现componentDidUpdate之前暂停setState -> componentDidUpdate触发。

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

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