React入門２: 盤面の作成

# はじめに
私自身の復習兼、備忘録的な意味もあり、複数回の記事に渡って React を用いてマルバツゲーム(三目並べ)を開発していきたいと思います。
- [React](https://ja.react.dev/)
- [CodeSandbox(公式)](https://codesandbox.io/)
- [CodeSandbox(非公式の日本語ガイド)](https://csb-jp.github.io/)

## シリーズの一覧
1. [React入門１: 環境構築 [オンライン版]](https://qiita.com/banana_bancho/items/64fa6ccb58101eadbb63)
   - [React入門1.5: 環境構築 [ローカル版-番外編]](https://qiita.com/banana_bancho/private/30f5d9d2c5eea00ac11c)
1. React入門２: 盤面の作成 (今回)
1. [React入門３: インタラクションの実装](https://qiita.com/banana_bancho/private/557d14b2413cb0317ce4)
1. [React入門４: リファクタリング [リフトアップ編]](https://qiita.com/banana_bancho/private/81730326c004e52c6aad)
1. [React入門５: リファクタリング [インタラクション編]](https://qiita.com/banana_bancho/private/3f20d23aadb49fe233f8)
1. [React入門６: 手番の実装](https://qiita.com/banana_bancho/private/6bed838f67e575f58b72)
1. [React入門７: ゲームの勝利判定](https://qiita.com/banana_bancho/private/c0eca4e9348edb430561)
1. [React入門８: テキストの実装](https://qiita.com/banana_bancho/private/b841b1ce38482b31753c)
1. [React入門９: タイムトラベル(1)](https://qiita.com/banana_bancho/private/c674872e32fcb52bb2a0)
1. [React入門10: タイムトラベル(2)](https://qiita.com/banana_bancho/private/861398f1fa4efd378938)
1. [React入門11: タイムトラベル(3)](https://qiita.com/banana_bancho/private/0d3cf7e1b1ebbf20c5e0)

# 目的について
## 全体の目的
React公式のチュートリアルで公開されているマルバツゲームを 3x3 のマスで実装していきます。

https://ja.react.dev/learn/tutorial-tic-tac-toe

## 今回の目的
3x3 のマスで構成された盤面を作成していきます。いよいよコーディングを開始です。

# 開発
次のページで、前回のソースファイルを確認できます。

https://codesandbox.io/p/sandbox/react-tutorial1-hstpll

- 前回の内容はコチラから！

https://qiita.com/banana_bancho/items/64fa6ccb58101eadbb63

## マスの作成
App.js に次のコードを記述しましょう。
```jsx: App.js
export default function Square() {
  return (
      <button className="square">X</button>
  );
}
```
```export default``` は、App.jsがインポートされたときに実行されるコンポーネント(関数)を示します。ここでは、App.js が index.js にインポートされることで ```Square``` コンポーネントが呼び出されます。なお、コンポーネント名はアルファベットの大文字から始まる必要があります。

```return``` 文を見ると、```<button>``` タグが記述されており、一般的な JavaScript と異なった構文となっていますね。このような HTML と JavaScript を混ぜたような文法を JSX といいます。

これでマスに「X」が記されたマスが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/e84f18fd-2b2e-4b23-d804-f117b6701ca6.png)

このままでは、見た目が味気ないので styles.css でマスの装飾をしていきます。
```css:styles.css
.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;
}
```

装飾を反映させるために、App.js で styles.css を読み込みます。
```jsx: App.js
import "./styles.css";

export default function Square() {
  return (
      <button className="square">X</button>
  );
}
```

これで styles.css のスタイルが適用されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/d54b50f9-d7a5-c767-797e-531f62cad4ee.png)

## 盤面の作成
次に複数のマスを表示して、盤面の作成していきましょう。

### 2つのマスを表示する
まずは、2つのマスを表示させます。
```jsx: App.js
import "./styles.css";

export default function Square() {
  return (
    <>
      <button className="square">X</button>
      <button className="square">X</button>
    </>
  );
}
```

動作結果は、次のようにマスが横方向並んで表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/dddd293c-1feb-c92f-c0cf-67c4dc209e55.png)

#### フラグメント ```<>```
```return``` 文では2つの ```<button>``` 要素が ```<>``` という空の要素で囲まれていますね。React では、これをフラグメントといい、複数の要素を返す際に利用されます。次のように、フラグメントを欠いて複数要素を返すとエラーが出力されます。
- プログラム
    ``` jsx
    return (
      <button className="square">X</button>
      <button className="square">X</button>
    );
    ```
- エラー
    ```
    /src/App.js: Adjacent JSX elements must be wrapped in an enclosing tag. 
    Did you want a JSX Fragment <>...</>?
    ```

### 3x3の盤面を作成する
2つのマスを表示させたときと同様に、```return``` 文内に ```<button>``` 要素を9つ記述していきましょう。

```jsx: App.js
import "./styles.css";

export default function Square() {
  return (
    <>
      <button className="square">X</button>
      <button className="square">X</button>
      <button className="square">X</button>
      <button className="square">X</button>
      <button className="square">X</button>
      <button className="square">X</button>
      <button className="square">X</button>
      <button className="square">X</button>
      <button className="square">X</button>
    </>
  );
}
```

動作結果は、9つのマスが1行に表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/ee1141ff-fe12-460b-e600-19fb23db2204.png)

そこで、```<button>``` 要素を ```<div>``` 要素で3個ずつまとめましょう。各 ```<div>``` 要素には同じ ```className``` を指定しましょう。
```jsx: App.js
import "./styles.css";

export default function Square() {
  return (
    <>
      <div className="board-row">
        <button className="square">X</button>
        <button className="square">X</button>
        <button className="square">X</button>
      </div>
      <div className="board-row">
        <button className="square">X</button>
        <button className="square">X</button>
        <button className="square">X</button>
      </div>
      <div className="board-row">
        <button className="square">X</button>
        <button className="square">X</button>
        <button className="square">X</button>
      </div>
    </>
  );
}
```

```<div>``` 要素ごとを行とするために、styles.css に次を追記しましょう。[```::after``` 疑似要素](https://developer.mozilla.org/ja/docs/Web/CSS/::after) によって ```<div>``` 要素の後に関するスタイリングができます。

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

これで 3x3 の盤面ができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/5fb950a5-3625-fa4f-6cef-da1201aa1e64.png)

### コンポーネントの分解
ここで App.js のプログラムを振り返ると、```Square``` コンポーネントで複数のマスを直接的にコーディングすることで、盤面が作成されていますね。

これを次のような構成に分解してみます。
- ```Board``` コンポーネント (親コンポーネント)
  - 盤上を構成する要素
  - 複数の ```Square``` コンポーネントを呼ぶ
- ```Square``` コンポーネント (子コンポーネント)
  - マスを構成する要素
  - 呼ばれるときには、マス内に表示する文字を受け取る

![コンポーネント化.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/7a252248-023d-7548-50b5-0c498660ce7e.jpeg)

App.js のプログラムを次のように変更しましょう。
- ```Board``` コンポーネントを実装する
    - 「```export default function Square()```」のリネーム
      コンポーネント名 ```Square()``` を ```Board()``` に変更する
    - ```<button className="square">X</button>``` を ```<Square />``` に変更する
- 新たに ```Square``` コンポーネントを実装する
    - プロパティ(引数)として ```value``` を加える
    - ```<button>``` 要素で ```value``` プロパティの値を表示させる

```jsx:App.js
import "./styles.css";

function Square({ value }) {
  return <button className="square">{value}</button>;
}

export default function Board() {
  return (
    <>
      <div className="board-row">
        <Square value="X" />
        <Square value="X" />
        <Square value="X" />
      </div>
      <div className="board-row">
        <Square value="X" />
        <Square value="X" />
        <Square value="X" />
      </div>
      <div className="board-row">
        <Square value="X" />
        <Square value="X" />
        <Square value="X" />
      </div>
    </>
  );
}
```

#### 波括弧 ```{}``` の文法的意味
```Square``` コンポーネントを注目すると波括弧 ```{}``` が記述されていますね。JSX で JavaScript の構文を利用する際には、この波括弧が必要です。```Square``` コンポーネントでは、次の2つを実現するために ```{value}``` が記述されています。
- ```Square``` コンポーネントのプロパティを設定する
- プロパティの値を ```<button>``` 要素に表示する

これを省略するとどうなるのか、試してみましょう。

```jsx: App.js: Squareコンポーネント
function Square(value) {
  return <button className="square">value</button>;
}
```

結果、次のように ```value``` が文字列として認識されます。これは HTML での [```<button>``` 要素](https://developer.mozilla.org/ja/docs/Web/HTML/Element/button) と同様の結果であることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2844961/7132cc5b-9669-060c-5d66-1472f5071537.png)

# おわりに
今回は、```Square``` コンポーネントと ```Borad``` コンポーネントで盤面を作成していきました。次のページに現段階のソースファイルを示します。

https://codesandbox.io/p/sandbox/react-tutorial2-y2wlsd

次回は盤面上にあるマスに対してマウスによるインタラクションを実装していきます！

https://qiita.com/banana_bancho/items/557d14b2413cb0317ce4