入門」シリーズ第2回は、クリックしたマス目に「X」印をつけます。9つのマス目のデータやその操作をどこで行い、コンポーネント間でどのようにやり取りするのかがポイントです。盤面のモジュールsrc/components/Board.jsのJSXにおけるつぎのような3マス1行の要素を配列でつくることにしましょう。className="board-row">{renderSquare(0)}{renderSquare(1)}{renderSquare(2)}</div></div>);};要素は別に用意したデータにもとづいてつくることが少なくありません。今回はマス目をつくる関数(renderSquare())に引数の数値を渡すだけです。空の要素3つの配列さえあれば足ります。このとき使うのがArray.from()メソッドです。第2引数としてマップ関数を与えれば、その戻り値を要素に収めた新たな配列が返されます。Array()関数に要素数だけ定めた空要素の配列には、Array.prototype.map()メソッドは使えません(「Array.from()メソッド」参照)。関数の引数に与えたアンダースコア(_)ひと文字は、関数の中で使わないという意味を示すことがあります。新たな配列に収める要素)盤面のモジュールsrc/components/Board.jsに加える3マス1行の要素を返す関数(renderRow())は、つぎのように定めました。配列で動的に要素をつくるときは、それぞれkeyプロパティに一意の値を与えてください。データをルートコンポーネントにもたせるマルバツのデータは9マス分まとまっていないと、勝ち負けの判定などの処理ができません。そこで、ルートコンポーネントsrc/components/App.jsにもたせることにしましょう。盤面のコンポーネント(Board)にまとめることも、できないではありません。盤面はデータの表示、データとその操作はルートコンポーネントとするのが、わかりやすい切り分けです。データをもって子コンポーネントに渡し、参照させるためには、src/components/App.jsは関数でなくクラスコンポーネントに書き直さなければなりません。クラスコンポーネントは、つぎのようにReact.Componentを継承します。備えなければならないのが、render()メソッドです。関数コンポーネントに定めていたreturn文を、この本体に移します。インスタンスにデータを収める特別なプロパティがstateです。constructor()の中で、オブジェクトのかたちでプロパティにデータを与えて初期化してください(「constructor()」参照)。9マスのデータ(squares)は配列にして、要素は確認用にすべて文字列'X'にしました。空要素の配列に引数の値を埋め込むために用いたのがArray.prototype.fill()メソッドです。/></div>);};}親コンポーネントから属性(squares)のかたちで与えられた値は、関数コンポーネントの引数(props)から参照できます。その値を、さらにバケツリレーで子コンポーネント(Square)に属性として渡しているのがつぎのsrc/components/Board.jsのコードです。これでルートコンポーネントのデータの値が、9つのマス目にそれぞれ示されます(図001)。クリックしたマス目に印をつけるマス目ははじめ空白にし、クリックしたら印をつけるようにしましょう。このときも、データを書き替えるのはルートコンポーネントです。クリックするのはマス目ですから、今度は子から親への逆バケツリレーになります。テンプレートの要素がクリックされたことを捉えるのは、onClickイベントです(「イベント処理」参照)。子コンポーネント(src/components/Square.js)がpropsから参照して呼び出すハンドラ関数(onClick())は、親コンポーネント(src/components/Board.js)が与えます。ような)イベントハンドラを渡すには?」参照)。引数(i)に渡されるのがクリックしたマス目のインデックスです。プロパティstateは、constructor()呼び出しのあとは直に書き替えることはできず、メソッドsetState()を用いなければなりません。引数はオブジェクトで、変更するプロバティ(squares)に新たな値を与えます。値となる配列は、スプレッド構文...により複製したうえで要素を書き替えました。setState()メソッドの引数オブジェクトはオブジェクトの分割代入を用いて渡しています。this.handleClick(i)}/></div>);};}注意すべき点として、イベントハンドラのメソッド(handleClick())がthisを参照する場合は、あらかじめconstructor()の本体でFunction.prototype.bind()によりthisをバインドしておくようにしましよう(「関数をコンポーネントインスタンスにバインドするには?」参照)。これではじめはnullで空白にしたマス目に、クリックするとX印がつきます(図002)。前掲コードでは、変更するプロバティ(squares)に、値の配列はスプレッド構文...で複製してsetState()メソッドにより設定しました。もとのデータを直に書き替えない、これがイミュータビリティ(immutability)です(「イミュータビリティは何故重要なのか」参照)。オブジェクトの中身に直接手を加えると、Reactがいつどのような変更があったのか、検出に手間取ります。新たなデータで上書きすれば、変更がはっきりし、その影響範囲とくに描画の更新も最適化されるのです。イミュータビリティは、機能の実装をシンプルにしたり、バグが見つけやすくなるという利点もあります。書き替えた3つのモジュールは、つぎのコード001にまとめます。CodeSandboxに以下のサンプル001を掲げました。クリックしたマス目にXをつける」を大幅に改訂。