手を動かしながら学ぶReact入門 2. Reactについて学ぶ

WebフレームワークであるReactについて、実際に手を動かしながら学んでいきたいと思います。

1.　[Create React Appでプロジェクトの雛形を作成](https://qiita.com/basio/items/998cbcb2be16e2f2a084)
2.　Reactについて学ぶ ←　ここ
3.　[三目並べを関数コンポーネントで実装する](https://qiita.com/basio/items/f1ce1f3747463e7ad0e5)

# Reactについて学ぶ
[先で作成した](https://qiita.com/basio/items/998cbcb2be16e2f2a084#hello-world)App.jsと、index.jsを見てみましょう。

```jsx:App.js
function App() {
  return (
    <h1>Hello World</h1>
  );
}

export default App;
```

```javascript:index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

```

この関数Appが一つの**コンポーネント**としてindex.jsの中で呼び出されています。
index.jsはindex.htmlの`root`というIDの要素に対してAppコンポーネントを適用しているので、結果としてAppコンポーネント（この場合だとHello World）が表示されたわけですね。

関数Appの中を見ていると、なにやらJavaSciptの関数がHTMLのタグを返していますね。
この少し見慣れない構文を**JSX**と言います。

## JSX
上記のJSXはコンパイル時に下記のように変換されます。いわゆるシンタックスシュガーというやつです。

```javascript:App.js（コンパイル後）
function App() {
  return (
    React.createElement("h1", null, "Hello World");
  );
}

export default App;
```
createElementに変換されることで、DOMを作成しているわけですね。
`<h1>`タグ一つだけだったらこれだけでもいいかもしれませんが、階層構造になるとJSXがすごく見通しが良くなるのがわかると思います。

```jsx:App.js
function App() {
  return (
    <div>
        <h1>Hello World</h1>
        <p>foo</p>
        <p>bar</p>
    </div>
  );
}

export default App;
```
```javascript:App.js（コンパイル後）
function App() {
  return (
    React.createElement("div", null, React.createElement("h1", null, "Hello World"), React.createElement("p", null, "foo"), React.createElement("p", null, "bar"));
  );
}

export default App;
```

### 変数を使う
JavaScriptでDOMを定義できるので、もちろん変数を使うことができます。
JSX内で変数を扱うには波括弧でくくります。

```jsx:App.js
const name = "Basio";
function App() {
  return (
    <h1>Hi {name}</h1> // -> Hi Basio
  );
}

export default App;
```

波括弧内は変数だけでなく、式や文も入れ込めます。

```jsx:App.js
const count = 10;
function App() {
  return (
    <h1>Count is {count + 1}</h1> // -> Count is 11
  );
}
```


### forで回してみる
波括弧でくくればJavaScriptの文を入れ込めるため、forループも可能です。

```jsx:App.js
function App() {
  const array = ['foo', 'bar', 'baz'];
  return (
    <ul>
      {array.map(element=>{
        return <li>{element}</li>;
        })
       // -> <li>foo</li><li>bar</li><li>baz</li>
      }
    </ul>
  );
}

export default App;
```

## Component
[最初にも記載していますが](https://qiita.com/basio/items/998cbcb2be16e2f2a084)、Reactでは**コンポーネント**という単位で要素を作成し、それを組み合わせてUIを構築していきます。
コンポーネントは以前からある**クラスコンポーネント**とReact 16.8以降で導入された**関数コンポーネント**の2つがありますが、本稿では関数コンポーネントのみ扱います。
理由は他の人が色々挙げられていますが、個人的にJavaScriptのthisが非常にわかりにくいというのが大きなところです。
参考：[Reactでクラスコンポーネントより関数コンポーネントを使うべき理由5選](https://tyotto-good.com/blog/reaseons-to-use-function-component)

今の所実装しているコンポーネントは、ただJavaScriptでHTMLのコードをまとめただけのものですね。
コンポーネント（部品）というからには、作成時にプロパティを与えたり、状態をもたせたり、アクションを定義したりということが必要になってくると思います。
安心してください、もちろんそんな機能もコンポーネントには含まれています！

### props：プロパティ
コンポーネントに初期値を渡したいときはprops（プロパティの意）を使用します。
今までAppという名前のコンポーネントで通してきましたが、わかりやすいように今回はWelcomeという名前に変更します。
Welcomeコンポーネントはnameというプロパティを受け取って、表示する内容が変わるコンポーネントです。

```jsx:App.js
function Welcome(props) {
  return (
    <div>Hi {props.name}</div>
  );
}

export default Welcome;
```

```jsx:index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Welcome from './App';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <Welcome name="foo"/>
    <Welcome name="bar"/>
    <Welcome name="baz"/>
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

```
このように、propsの内容が設定されていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556091/68f3fb90-7137-6970-513a-7858a4ae2328.png)

ただし、このpropsについては一つ制約があり、**propsは読み取り専用でなければならない**です。
カウンターのように更新される値についてはpropsは使えないということですね。

### state : 状態
じゃあどうするのさ、って時にstateを使用します。
stateは変更可能な値を格納でき、stateが変更されたタイミングで画面も自動的に更新されます。
propsでは実現できなかったカウンターコンポーネントを作ってみましょう。

`setState`を使うことでstateの定義＆初期化、state更新用関数の定義が行えます。

```jsx:App.js
import React, {useState} from 'react';

function Counter() {
  const [count, setCount] = useState(0);  // 初期値0でcountを初期化 & state更新用関数setCountを定義
  return (
    <React.Fragment>
      <p>Count : {count}</p>
      <button onClick={()=>{setCount(count + 1)}}>
        Count Up
      </button>
    </React.Fragment>
  );
}

export default Counter;
```
```javascript:index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Counter from './App';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <Counter/>
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
```
「Count Up」ボタンをクリックすることでカウントが更新されるコンポーネントが実現できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556091/b31150ac-1ad9-492b-ec77-83e7f5a880e5.png)
stateを使うことで画面と紐付いた状態を実現することができていますね。

次は[公式の三目並べ](https://ja.reactjs.org/tutorial/tutorial.html)を関数コンポーネントだけで実装していきたいと思います。