React のチュートリアルを Typescript でやってみた【ソース準備編】

## 目次
- [React のチュートリアルを Typescript でやってみた【環境構築編】](https://qiita.com/humi/items/49a7472e9a10558ea5c0)
- [React のチュートリアルを Typescript でやってみた【環境構築編2】](https://qiita.com/humi/items/72485614151fe564dceb)
- [React のチュートリアルを Typescript でやってみた【ソース準備編】](https://qiita.com/humi/items/8e0933d992215b5f70d3) ←ここ
- [React のチュートリアルを Typescript でやってみた1](https://qiita.com/humi/items/3d4df671633b7d0f7db3)
- [React のチュートリアルを Typescript でやってみた2](https://qiita.com/humi/items/f56214d859a0cf37a895)
- [React のチュートリアルを Typescript でやってみた3](https://qiita.com/humi/items/33e34183ccab3ff60a3b)


## 概要
チュートリアル通りにやりますが、端折る箇所もあると思います。  
各々保管をお願いいたします。  
今回はソースを用意するところまでやります。

## 公式のチュートリアルページ
* [チュートリアル：React の導入](https://ja.reactjs.org/tutorial/tutorial.html)

## スタートコードを用意する
スタートコードがなければ始まらないので以下のスタートコードを用意します。
- index.html
　srcフォルダに設置
- index.css
　distフォルダに設置
- index.tsx
　開発環境に合わせるため内容を変更しています。
　srcフォルダに設置

```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>TypeScript HelloWorld</title>
    <link rel="stylesheet" href="./index.css" />
  </head>
  <body>
    <div
      id="errors"
      style="
            background: #c00;
            color: #fff;
            display: none;
            margin: -20px -20px 20px;
            padding: 20px;
            white-space: pre-wrap;
          "
    ></div>
    <div id="root"></div>
    <script>
      window.addEventListener("mousedown", function(e) {
        document.body.classList.add("mouse-navigation");
        document.body.classList.remove("kbd-navigation");
      });
      window.addEventListener("keydown", function(e) {
        if (e.keyCode === 9) {
          document.body.classList.add("kbd-navigation");
          document.body.classList.remove("mouse-navigation");
        }
      });
      window.addEventListener("click", function(e) {
        if (e.target.tagName === "A" && e.target.getAttribute("href") === "#") {
          e.preventDefault();
        }
      });
      window.onerror = function(message, source, line, col, error) {
        var text = error
          ? error.stack || error
          : message + " (at " + source + ":" + line + ":" + col + ")";
        errors.textContent += text + "\n";
        errors.style.display = "";
      };
      console.error = (function(old) {
        return function error() {
          errors.textContent +=
            Array.prototype.slice.call(arguments).join(" ") + "\n";
          errors.style.display = "";
          old.apply(this, arguments);
        };
      })(console.error);
    </script>
  </body>
</html>

```

```css:index.css
body {
  font: 14px "Century Gothic", Futura, sans-serif;
  margin: 20px;
}

ol, ul {
  padding-left: 30px;
}

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

.status {
  margin-bottom: 10px;
}

.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;
}

.square:focus {
  outline: none;
}

.kbd-navigation .square:focus {
  background: #ddd;
}

.game {
  display: flex;
  flex-direction: row;
}

.game-info {
  margin-left: 20px;
}
```

```tsx:index.tax
import * as React from "react";
import * as ReactDOM from "react-dom";
import { hot } from "react-hot-loader/root";

class Square extends React.Component {
  render() {
    return (
      <button className="square">
        {/* TODO */}
      </button>
    );
  }
}

//型指定しなければエラーが出るため型指定する。
class Board extends React.Component {
  renderSquare(i:number) {
    return <Square />;
  }

  render() {
    const status = 'Next player: X';

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

class Game extends React.Component {
  render() {
    return (
      <div className="game">
        <div className="game-board">
          <Board />
        </div>
        <div className="game-info">
          <div>{/* status */}</div>
          <ol>{/* TODO */}</ol>
        </div>
      </div>
    );
  }
}

//hot 機能を使用するため
export default hot(Game);

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

```

## ファイルを分ける
せっかくなのでコンポーネントごとにファイルをしたいと思います。  

1. srcフォルダ直下に以下のフォルダを作成
    * components

2. componentsフォルダに以下のファイルを作成
    * game.tsx
      * ソースファイル
    * game
      * フォルダ（自身の子のコンポーネントは同名フォルダ内に入れるらしい）

3. gameフォルダ内に以下のファイルを作成
    * board.tsx
    * square.tsx

### 各ソースの内容
上記を用意したことでソースの変更をします。変更及び新規ソースは以下になります。
* square.tsx
* board.tsx
* game.tsx
* index.tsx

```tsx:square.tsx
import * as React from "react";
import { hot } from "react-hot-loader/root";

class Square extends React.Component {
  render() {
    return (
      <button className="square">
        {/* TODO */}
      </button>
    );
  }
}

export default hot(Square);
```

```tsx:board.tsx
import * as React from "react";
import { hot } from "react-hot-loader/root";
import Square from "./square";

class Board extends React.Component {
  renderSquare(i: number) {
    return <Square />;
  }

  render() {
    const status = 'Next player: X';

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

export default hot(Board);
```

```tsx:game.tsx
import * as React from "react";
import { hot } from "react-hot-loader/root";
import Board from "./game/board";

class Game extends React.Component {
  render() {
    return (
      <div className="game">
        <div className="game-board">
          <Board />
        </div>
        <div className="game-info">
          <div>{/* status */}</div>
          <ol>{/* TODO */}</ol>
        </div>
      </div>
    );
  }
}

export default hot(Game);
```

```tsx:index.tsx
import * as React from "react";
import * as ReactDOM from "react-dom";
import Game from "./components/game";

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

以下のようなソースの配置になりました。
![スクリーンショット 2020-06-16 0.50.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149239/fe2ffa54-6661-f0a1-1731-d6468ffa4c64.png)


今回はここまで
コンポーネントぽく書いてみましたが正解かわからないです。