Lift up! tic-tac-toe:React Tutorial For Myself

Fine,again I go back in these noisy skills for prod

Today we will go around the tutorial:tic-tac-toe game


井字棋为什么要叫tic-tac-toe?

We will learn these thought:

  • polymorphic 多态

  • lift state up 状态提升

  • function component 函数组件

State Everywhere

 class Square extends React.Component {
      constructor(props){
          super(props);
          this.state = {
              value:null
          }
      }
      render() {
        return (
            <button className="square" 
        // set up a click event listener to go methods
        onClick={() => this.props.onClick()}>
        {this.props.value}
        </button>
        );
    }
}

Lift state up

Using Array to store state
Using feature of React to bind Data and methods

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

class Board extends React.Component {
    //State is stored in the Board
    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//这句话牛逼
        });
    }
    //给Square绑定
    renderSquare(i) {
        //Since the Board passed onClick={() => this.handleClick(i)} 
        //to Square
        //the Square calls this.handleClick(i) when clicked.
        return <Square value={this.state.squares[i]}
        onClick={() => this.handleClick(i)}  />;
    }

    render() {
        //let status = 'Next player: X';
        //还能这样?
        const winner = calculateWinner(this.state.squares);
        let status;
        if (winner) {
          status = 'Winner: ' + winner;
      } else {
          status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
      }

      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>
        );
  }
}
  1. The onClick prop on the built-in DOM <button> component tells React to set up a click event listener.
  2. When the button is clicked, React will call the onClick event handler that is defined in Square’s render() method.
    This event handler calls
  3. this.props.onClick(). The Square’s onClick prop was specified by the Board.
  4. Since the Board passed onClick={() => this.handleClick(i)} to Square, the Square calls this.handleClick(i) when clicked.

Lift state up twice

Why?Because we want to have the whole situation state could be stored or even dated back, which is the reason why we use .slice() instead of modifying the existing array
Immutability Is Important

Have board be a num render and a middleman for Square
1:Move off the constructor(state) to Game component using correct data construction
2:Move to method of controling state to Game component correctly(sometimes needs to change)
3:Don't forget to connect Game and board by:

return  (
//....
<Board
           squares={current.squares}
           onClick={(i) => >this.handleClick(i)}
         />
     </div> 
)

and be careful about all the minor details

<div>{ status }</div>//in return of Game
<Square
        value={this.props.squares[i]}
        onClick={() => this.props.onClick(i)}
      />
//have changed in return of Board from  this.state.squares[i] and this.handleClick(i) 
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>
    );
  }
}

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

  handleClick(i) {
    const history = this.state.history;
    const current = history[history.length - 1];
    const squares = current.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      history: history.concat([{
        squares: squares,
      }]),
      xIsNext: !this.state.xIsNext,
    });
  }

  render() {
    const history = this.state.history;
    const current = history[history.length - 1];
    const winner = calculateWinner(current.squares);
    let status;
    if (winner) {
      status = 'Winner: ' + winner;
    } else {
      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    }

    return (
      <div className="game">
      <div className="game-board">
      <Board
            squares={current.squares}
            onClick={(i) => this.handleClick(i)}
          />
      </div>
      <div className="game-info">
    <div>{ status }</div>
  <ol>{/* TODO */}</ol>
  </div>
  </div>
  );
  }
}

Now we could have many state situations in the Object Array and never lose them.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容