LoginSignup
6
8

More than 3 years have passed since last update.

[React][Reactチュートリアル]ふりがな

Posted at

はじめに

React.jsを知るためにReactチュートリアルを使用しました。
その際に書いたコードに自分なりのふりがなをつけたため、記事として残したいと思います。

チュートリアル:React の導入

index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

function Square(props) {
  return (
    // 盤面に'X'または'Y'を表示させる
    <button
      className="square"
      onClick={props.onClick}>
      {props.value}
    </button>
  )
}

class Board extends React.Component {
  renderSquare(i) {
    return (
      // マス目の番号である1~9の数字が渡されてくる
      <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に変化していく盤面の状態を都度保存する
      history: [{
        // 最初の盤面の状態として3x3の計9マスに初期値として、それぞれにnullを保存する
        squares: Array(9).fill(null),
      }],
      // stepNumberで今が何手目なのかを保存していく
      stepNumber: 0,
      // プレイやーを判断する
      // xIsNext = trueの時は'X', falseの時は'O',
      xIsNext: true,
    };
  }

  handleClick(i) {
    // 過去の履歴に戻った際にstepNumber + 1以降のデータを削除して更新
    const history = this.state.history.slice(0, this.state.stepNumber + 1);
    const current = history[history.length - 1];
    const squares = current.squares.slice();
    // 勝負がついている場合、returnによりhandleClickを終了させ入力をさせない
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      // 元のhistoryを更新しないためにconcatを使用
      history: history.concat([{
        squares: squares,
      }]),
      // 現在の手数で更新
      stepNumber: history.length,
      // !this.state.xIsNextで毎回trueとfalseを反転させて更新
      xIsNext: !this.state.xIsNext,
    });
  }

  jumpTo(step) {
    this.setState({
      // stepNumberに選択された履歴番号(何手目か)で更新
      stepNumber: step,
      // 選択された履歴のプレイヤーを判定する
      xIsNext: (this % 2) === 0,
    });
  }

  render() {
    const history = this.state.history;
    // stepNumberを基準に盤面の現状を更新
    const current = history[this.state.stepNumber];
    // calculateWinnerに現状の盤面情報を渡し勝者情報をwinnerに代入
    const winner = calculateWinner(current.squares);

    // 履歴に戻るボタンを履歴数分作成し、movesに代入
    const moves = history.map((step, move) => {
      // 履歴の有無で条件分岐してテキストを代入
      const desc = move ?
        'Go to move #' + move :
        'Go to game start';
      return (
        // この配列(履歴)は途中で要素の変更などがされないためkeyにはインデックス番号を使用します
        <li key={move}>
          {/* 履歴に戻るボタンを作成
          押されるとjumpTo関数をコールし、戻る履歴の番号を渡す */}
          <button onClick={() => this.jumpTo(move)}>
            {desc}
          </button>
        </li>
      );
    });

    // ゲーム状況に応じてstatusにアナウンスする文を代入する
    let status;
    if (winner) {
      // 勝者がいる場合(ゲームが終了した場合)
      status = 'Winner: ' + winner;
    } else {
      // 勝者がいない場合(ゲームが継続する場合)
      // xIsNextの真偽知によって次のプレーヤー('X' または 'O')を表示する
      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>{moves}</ol>
        </div>
      </div>
    );
  }
}

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

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

// 勝ち判定メソッド
function calculateWinner(squares) {
  // 全ての勝ちパターンを配列代入する
  const lines = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];
  // 勝ちパターンの数だけ繰り返す
  for (let i = 0; i < lines.length; i++) {
    // linesから取り出した要素を、さらに1つずつa,b,cに代入する
    const [a, b, c] = lines[i];
    // 現在の盤面が勝ちパターンと一致しているかを判定
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      // 一致していれば勝者('X' または 'O')を返す
      return squares[a];
    }
  }
  // 勝者がいなければnullを返す
  return null;
}

6
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8