php_modが非推奨になったのね

昔のバージョンのphp環境でphpバージョンを上げるという対応中。 apache + PHP8のインスタンスを構築してドキュメントルートまで到達を確認。 対応する人にドキュメントルートまで到達するからプロジェクトのファイルを置いてバージョンアップのエラーを確認してもらうため依頼しましたが HTTP 503 Service Unavailable のエラーが出ているとのこと。 HTMLファイルはアクセスできているからPHPの実行ができていないと思い調べると Apache HTTP サーバーで使用するために PHP に提供されている mod_php モジュールが非推奨になりました。 php-fpmをインストールして起動し、リクエストを流してphp-fmpでphpを実行するようにして解決。 しばらくPHPを触っていなかったのでモジュールが非推奨になったことに気づかずでした。

Reactを初めて触ってみました(tutorialその⑦)

Reactを初めて触ってみました(tutorialその⑦)

このページはReact公式ページのtutorialを体験したメモと初心者なりの解釈を記述したページになります。
前回までは基本となるゲームの作りまで完成しました。ここからは履歴の機能に取り掛かっていきます。
※WEB翻訳をそのまま載せているところもありますが自分で理解できるように記事にしています。

歴史の保存
ボードの古い状態に戻って、以前の動きの後にどのように見えるかを見ることができるようにしましょう。
移動が行われるたびに、すでに新しい四角形配列が作成されています。
これは、過去のボード状態を同時に簡単に保存できることを意味します。

このようなオブジェクトをstateに格納しようとしましょう

history = [
  {
    squares: [
      null, null, null,
      null, null, null,
      null, null, null,
    ]
  },
  {
    squares: [
      null, null, null,
      null, 'X', null,
      null, null, null,
    ]
  },
  // ...
]

トップレベルのゲームコンポーネントが移動リストの表示を担当するようにします。
それで、スクエアからボードに前の状態を引き上げたように、BoardからGameに再びプルアップしましょう。トップレベルで必要なすべての情報を得ることができます。
四角形のクリック操作でBoardの値を変更したようにBoardからGameへ値を渡しましょうってところでしょうか。

最初に、コンストラクタを追加してGameの初期状態を設定します。
class Game extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      history: [{
        squares: Array(9).fill(null),
      }],
      xIsNext: true,
    };
  }
・・・・・・

ボードを変更して、小道具(props)を介して四角形を取り、Squareが以前に行った変形のように、Gameによって指定された独自のonClick小道具を持っています。
各四角の位置をクリックハンドラに渡すことができるので、クリックされた四角形はまだわかります。
必要な手順の一覧は次のとおりです。

ボードでコンストラクタを削除します。
ボードのrenderSquareでthis.state.squares[i]をthis.props.squares[i]に置き換えます。
ボードのrenderSquareでthis.handleClick(i)をthis.props.onClick(i)に置き換えます。
ボード全体のコンポーネントは次のようになります。

class Board extends React.Component {
  handleClick(i) {
    const squares = this.state.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }

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

  render() {
    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>
    );
  }
}

ゲームのレンダリングでは、最新の履歴エントリが表示され、ゲームステータスの計算を引き継ぐことができます。
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>
    );
  }

ゲームがステータスをレンダリングしているので、ボードのレンダリング機能からステータスを計算する<div className = "status"> {status} </ div>とコードを削除できます。

次に、handleClickメソッド実装をBoardからGameに移す必要があります。
Boardクラスから切り取り、Gameクラスに貼り付けることができます。

ゲームの状態は構造が異なるため、少し変更する必要があります。
GameのhandleClickは、新しい履歴項目を連結して新しい履歴配列を作成することによって、新しい項目をスタックにプッシュすることができます。

  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,
    });
  }

この時点で、BoardはrenderSquareとrenderだけを必要とします。 状態の初期化とクリックハンドラは両方ともゲームに存在する必要があります。

翻訳とちょこっと自分的な説明を加えましたがonClickの部分がちょっと理科できないでいました。調べると理解出来なのでメモしておきます。

BoardのrenderSquareでSquareのonClickが以下になるとどうなるか

onClick={() => this.props.onClick(i)}

ちょっとはじめはコードを読んでいてもちゃんと理解はできていなかったのですがドキュメントとネットをみて理解しました。

まずはpropsの概念を理解していませんでした。
ドキュメント Components and Props

javascript関数で引数として渡すこともできて
ES6クラスを使用してコンポーネントを定義してthis.props.nameを利用できるようです。
ここもわかりやすく参考になりました。
React.jsのProp

つまりはGameでレンダリングするようにした
<Board
  squares={current.squares}
  onClick={(i) => this.handleClick(i)}
/>

こうなっていることで四角形をクリックしたらBoardの属性のonClickが実行されるんですね。そうして this.handleClick(i) が実行される。
でどの番号の四角形がクリックされたのかをもらい状態を変化しGameのstateで保存する。

はじめは複雑になったのではと思いましたが
見た目上の動作は変わりませんが状態をGameコンポーネントで管理して機能としてはわかりやすく全体的なプロパティの操作もしやすくなったというように見えます。

今回はここまでにしておきます。

←Reactを初めて触ってみました(tutorialその⑥)
→Reactを初めて触ってみました(tutorialその⑧)

コメント

このブログの人気の投稿

nginxで画像が表示されない。。

AWSのS3バケットをマウントするs3fsでマウントが外れた件

CakePHP3でHTTPSにする