SOURCE

console 命令行工具 X clear

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

// 每行
class RowsBox extends React.Component {
    squareOnClick (inx) {
    let squares = this.props.squares.slice()
    if (!squares[inx]) {
        let hitsoryList = this.props.hitsoryList ? this.props.hitsoryList : []
        let hitsoryListInx = hitsoryList.length
        hitsoryList[hitsoryListInx] = squares
        this.props.listGet(hitsoryList, inx)
      }
    }
    renderSquare (inx) {
        return (
            <Square
            value={this.props.squares[inx]}
            onClick={() => this.squareOnClick(inx)}
        />)
    }
    render () {
	    let rowList = []
	    for(let inx = 0; inx < 5; inx++) {
	    	rowList[inx] = +this.props.inx + inx
	    }
        let fixList = rowList.map((item) => (this.renderSquare(item)))
        console.log(rowList)
        return (
            <div className="board-row">
                {fixList}
            </div>
        )
    }
}

// 棋盘
class Board extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
          squares: Array(25).fill(null),
          xIsNext: true,
          hitsoryList: []
        }
    }
    backbtnClick () {
        if (this.state.hitsoryList.length) {
            let popHitsoryList = this.state.hitsoryList.slice()
            popHitsoryList.pop()
            this.setState({
                squares: this.state.hitsoryList[this.state.hitsoryList.length - 1],
                hitsoryList: popHitsoryList,
                xIsNext: !this.state.xIsNext
            })
        }
    }
    listGet(list, inx) {
        let squares = this.state.squares.slice()
        squares[inx] = this.state.xIsNext ? 'X': 'O'
        console.log(squares)
        this.setState({
            squares: squares,
            hitsoryList: list,
            xIsNext: !this.state.xIsNext
        })
    }
    render() {
      return (
        <div>
          <div className="status">现在轮到   {this.state.xIsNext ? 'X' : 'O'}           </div>
          <button onClick={() => {this.backbtnClick()}}>上一步</button>
          <RowsBox listGet={this.listGet.bind(this)} inx="0" xIsNext={this.state.xIsNext} squares={this.state.squares} hitsoryList={this.state.hitsoryList} callback={this.listGet.bind(this)} />
          <RowsBox listGet={this.listGet.bind(this)} inx="5" xIsNext={this.state.xIsNext} squares={this.state.squares} hitsoryList={this.state.hitsoryList} callback={this.listGet.bind(this)} />
          <RowsBox listGet={this.listGet.bind(this)} inx="10" xIsNext={this.state.xIsNext} squares={this.state.squares} hitsoryList={this.state.hitsoryList} callback={this.listGet.bind(this)} />
          <RowsBox listGet={this.listGet.bind(this)} inx="15" xIsNext={this.state.xIsNext} squares={this.state.squares} hitsoryList={this.state.hitsoryList} callback={this.listGet.bind(this)} />
          <RowsBox listGet={this.listGet.bind(this)} inx="20" xIsNext={this.state.xIsNext} squares={this.state.squares} hitsoryList={this.state.hitsoryList} callback={this.listGet.bind(this)} />
        </div>
      );
    }
}

// 整个盒子
class Game extends React.Component {
  render() {
    return (
      <div className="game">
        <div className="game-board">
          <Board />
        </div>
      </div>
    );
  }
}

// ========================================

// 渲染
ReactDOM.render(
  <Game />,
  document.getElementById('root')
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>  
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>

<script src="https://cdn.bootcss.com/prop-types/15.7.2/prop-types.min.js"></script>

<script src="https://cdn.bootcss.com/redux/4.0.1/redux.min.js"></script>
<srcipt src="https://cdn.bootcss.com/react-redux/7.1.0-rc.1/react-redux.min.js"></srcipt>

<div id="root"></div>
body {
  font: 14px "Century Gothic", Futura, sans-serif;
  margin: 20px;
}

ol, ul {
  padding-left: 30px;
}

.board-row:after {
  clear: both;
  content: "";
  display: table;
}

.status {
  margin-bottom: 10px;
}

.square {
  background: #fff;
  border: 1px solid #999;
  float: left;
  font-size: 24px;
  font-weight: bold;
  line-height: 34px;
  height: 34px;
  margin-right: -1px;
  margin-top: -1px;
  padding: 0;
  text-align: center;
  width: 34px;
}

.square:focus {
  outline: none;
}

.kbd-navigation .square:focus {
  background: #ddd;
}

.game {
  display: flex;
  flex-direction: row;
}

.game-info {
  margin-left: 20px;
}