React × Typescript で作る「いいね！」ボタン

# 対象読者
Reactを初めて触る人
TypeScriptがまだよくわかっていない人

# 完成品
[![Image from Gyazo](https://i.gyazo.com/c560ca188526c26bedcf104d53611a96.gif)](https://gyazo.com/c560ca188526c26bedcf104d53611a96)
[デモサイト](https://hashimoto-naoki.com/new/works/apps/like_btn/)

# 仕様ツール
- React(cretae-react-app)
- TypeScript
- styled-component

# Reactのインストール
`create-react-app` でReactのインストールをしていきます。
`template` オプションで、TypeScriptを指定します。

```terminal
npx create-react-app [任意のプロジェクト名] --template typescript
```
インストールに2分ほど時間がかかる

```terminal
cd [任意のプロジェクト名]
```
でプロジェクトフォルダーに移動する。

# Reactの起動
ターミナルで`npm start` とコマンドを打つと、
`http://localhost:3000/` で、ブラウザが起動する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519192/9367376e-48a2-cc6a-8d62-55727c7a1365.png)
こんな画面が表示されれば成功です！

# Reactの編集

src > App.tsx `<header>`タブ内を全て削除します。
代わりに、ダミーで「いいねボタン」のテキストを入れておきます。

```diff_javascript:App.tsx
function App() {
  return (
    <div className="App">
      <header className="App-header">
-        <img src={logo} className="App-logo" alt="logo" />
-        <p>
-          Edit <code>src/App.tsx</code> and save to reload.
-        </p>
-        <a
-          className="App-link"
-          href="https://reactjs.org"
-          target="_blank"
-          rel="noopener noreferrer"
-        >
-          Learn React
-        </a>
+        いいねボタン
      </header>
    </div>
  );
}
```

---
途中経過
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519192/9583a8ad-be98-dc21-d499-24d836582ae3.png)

# LikeButtonコンポーネントの作成

Appコンポーネントの下に、LikeButtonコンポーネントを追加します。
ダミーテキストとして「いいねボタン」を書いておきます。
```App.tsx
function App() {
  return ( 
        省略
  );
}

function LikeButton() {
  return (
    <span>いいねボタン</span>
  );
}
```
JavaScript内にHTMLを書ける**JSX**という記法です。
(TypeScriptのjsxなので、tsxという拡張子がつけられています。)

# classの追加

JSX/TSX内では、HTMLで使っていたclass属性は「**className**」で指定します。
これは、classがJavaScriptの予約語のため、名前が衝突しないようにするためです。

```diff_javascript:App.tsx
function App() {
  return ( 
        省略
  );
}

function LikeButton() {
  return (
-    <span>いいねボタン</span>
+    <span className='likeButton'>いいねボタン</span>
  );
}
```

# stateの追加

Reactでは、変化するデータは、ステート(状態)として扱います。
React Hooksの**useState**を使います。

useStateの定式
`const [ステートの名前, set+ステートの名前] = setState(初期値)`
ex) 
`const [name, setName] = setState("")`

ダミーテキストの「いいねボタン」の代わりに、ハートマークとcountの数字を代入してみましょう！
```App.tsx
(省略)

function LikeButton() {
  const [count, setCount] = useState(0);
  return (
    <LinkButton className='likeButton'>💛 {count}</LinkButton>
  );
}
```

# clickイベントの追加
Reactでのクリックイベントは`onClick`属性にコールバック関数を渡せばOK！
### クリックイベントの定式
`onClick={コールバック関数}`

慣例的に、`onClick`属性のコールバック関数は、`handleClick`(クリックを操作するの意味)で定義されることが多いです。
`handleClick`関数をアロー関数で定義して、`count`を１ずつ増やしてみましょう！

```diff_javascript:App.tsx
(省略)

function LikeButton() {
  const [count, setCount] = useState(0);
+  const handleClick = () => {
+    setCount(count + 1);
+  }
  return (
-    <LinkButton className='likeButton'>💛 {count}</LinkButton>
+    <LinkButton className='likeButton' onClick={handleClick}>💛 {count}</LinkButton>
  );
}
```

# LikeButtonの完成
以上で、LikeButtonコンポーネントの完成です。
完成コードを再掲します。
```App.tsx
(省略)

function LikeButton() {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount(count + 1);
  }
  return (
    <LinkButton className='likeButton' onClick={handleClick}>💛 {count}</LinkButton>
  );
}
```

# styled-componentの追加

JavaScriptの中にCSSを書く、 CSS in JS の代表格であるstyled-componentでボタンのスタイリングをしていきます。
まずは、インストールから
```terminal
npm install --save styled-components @types/styled-components
```
styled-components本体と、typeScript用にstyled-componentsの型定義をインストールしています。

styled-componentsのモジュールから、styledをimportする。
```diff_javascript:App.tsx
import React, { useState } from 'react';
+import styled from 'styled-components';
import './App.css';
```

### styled-componentsの書き方
```example.tsx
const コンポーネント名 = styled.タグ名`
    CSSの記述
`
```

今回は、`LinkButton`コンポーネントを<span>タグとしてスタイリングしていきます。

```App.tsx
const LinkButton = styled.span`
  background-color: rgb(231, 76, 60);
  color: white;
  padding: 0.8rem;
  border-radius: 0.4rem;
  cursor: pointer;
  user-select: none;
`
```

これでスタイリングの完成です！

# 完成コード
お疲れさまでした！
こちら全体の完成コードになるので、エラーが出れば、間違いがないかもう一度見返してみ下さい。

```App.tsx
import React, { useState } from 'react';
import styled from 'styled-components';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <LikeButton />
      </header>
    </div>
  );
}

function LikeButton() {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount(count + 1);
  }
  return (
    <LinkButton className='likeButton' onClick={handleClick}>💛 {count}</LinkButton>
  );
}

const LinkButton = styled.span`
  background-color: rgb(231, 76, 60);
  color: white;
  padding: 0.8rem;
  border-radius: 0.4rem;
  cursor: pointer;
  user-select: none;
`

export default App;
```