前回のおさらい
前回(第1回)は、9マス分表示するところで行いました。
まだ動きは何もついていない状態ですので、ここから動くようにしていきます。
現在のコードの問題点
今のApp.jsをもう一度みてみましょう。
export default function Board() {
return (
<>
<div className="board-row">
<button className="square">1</button>
<button className="square">2</button>
<button className="square">3</button>
</div>
<div className="board-row">
<button className="square">4</button>
<button className="square">5</button>
<button className="square">6</button>
</div>
<div className="board-row">
<button className="square">7</button>
<button className="square">8</button>
<button className="square">9</button>
</div>
</>
);
}
これを見て、改善できそうなポイントはありませんか?
前回、squareボタンを9個分コピペして作成したと思います。
数字だけ違いますが、buttonタグやクラス名は全く同じになっています。
このような「繰り返し要素」は1つのコンポーネントにまとめるのが鉄則です。
コンポーネントを分割
ではここでコンポーネントをSquareごとに分割します。
まずはSquareコンポーネントを、Boardコンポーネントの上に定義します。
// 追加
function Square() {
return <button className="square">1</button>;
}
export default function Board() {
return (
<>
<div className="board-row">
<button className="square">1</button>
<button className="square">2</button>
<button className="square">3</button>
</div>
<div className="board-row">
<button className="square">4</button>
<button className="square">5</button>
<button className="square">6</button>
</div>
<div className="board-row">
<button className="square">7</button>
<button className="square">8</button>
<button className="square">9</button>
</div>
</>
);
このSquareコンポーネントは、数字の「1」が入った1マスを表しています。
次にこれをBoardコンポーネントに埋め込みます。
function Square() {
return <button className="square">1</button>;
}
export default function Board() {
return (
<>
<div className="board-row">
<Square/>
<Square/>
<Square/>
</div>
<div className="board-row">
<Square/>
<Square/>
<Square/>
</div>
<div className="board-row">
<Square/>
<Square/>
<Square/>
</div>
</>
);
}
定義したコンポーネントを使う時には、
<Square/>
のような形式で書きます。
ここで実際に画面を見てみると、、、
1が9マス分入っています。
ここまででSquareコンポーネントに分割ができました。
propsを介してデータを渡す
次に、マスが全て1になってしまったので1~9が表示されるように修正します。
ここでReactの重要概念の1つ、「props」の理解が必要になります。
これは、関数がとる「引数」です。
早速propsを定義してみます。
function Square({ value }) { // 引数に{ value }を定義
return <button className="square">{ value }</button>;// buttonタグの中身を{ value }に変更
}
export default function Board() {
...略
画面では一旦空のマスになります。
次に数字を埋めていきましょう。
propsで定義した「value」に1を入れてみます。
function Square({ value }) {
return <button className="square">{ value }</button>;
}
export default function Board() {
return (
<>
<div className="board-row">
<Square value="1"/> // valueに1を入れる
<Square/>
<Square/>
</div>
<div className="board-row">
<Square/>
<Square/>
<Square/>
</div>
<div className="board-row">
<Square/>
<Square/>
<Square/>
</div>
</>
);
左上に1が入りましたか?
このようにしてBoardコンポーネントからSquareコンポーネントへ値を受け渡せるわけです。
では、残りの2~9を自力で埋めてみましょう。
回答はこんな感じです👇
function Square({ value }) {
return <button className="square">{ value }</button>;
}
export default function Board() {
return (
<>
<div className="board-row">
<Square value="1"/>
<Square value="2"/>
<Square value="3"/>
</div>
<div className="board-row">
<Square value="4"/>
<Square value="5"/>
<Square value="6"/>
</div>
<div className="board-row">
<Square value="7"/>
<Square value="8"/>
<Square value="9"/>
</div>
</>
);
}
どうでしょう、画面で1~9が並べばできています!
propsがわかれば、コンポーネントを分割できるようになるはずです!
今いまいち理解できていなくても、どんどん先に進みましょう!
インタラクティブなコンポーネントを作る
「三目並べ」を作るには、
マスをクリック=> マスに○か×をつける
動きが必要になります。
ここからはその動きをつけていきます。
Squareコンポーネントを次のように修正します。
function Square({ value }) {
function handleClick() {
console.log("clicked!");
}
return (
<button className="square" onClick={handleClick}>
{value}
</button>
);
}
ここでは「handleClick」関数を定義し、buttonのonClick属性に入れています。
ではブラウザの「検証ツール」を開き、consoleを確認します。
画面上のマスをクリックすると、
clickedが出ればOKです。
ここで次に実現したいのは、「マスをクリックして、Xを埋め込む」
ことです。
どうすれば良いでしょうか?
続きは次回でとりあげます。