Reactを触ってみる。

# Introduction
あくまで、自分用。

## 環境
- Ubuntu 18.04 ( vm with Vagrant
    - Node.js: v12.16. (>= 10.19.0
    - yarn: 1.22.4
        - npmでなくyarnを使うことにした。

## 参照したもの
- [ja.reactjs.org/docs](https://ja.reactjs.org/docs/getting-started.html)
- [create-react.dev](https://create-react-app.dev/docs/getting-started)
- [Reactに関する記事一覧 from to-R Media](https://www.to-r.net/media/tag/react/)

# Environment Setting
```sh:terminal
npm install --global yarn
yarn global add create-react-app
```

# Content
## 1st: yarn create react-app
```sh:terminal
# アプリ名に大文字は駄目だそうな。使ったら怒られた。
yarn create react-app hello-react
```

<details><summary>出力されたもの(折り畳み)</summary><div>

```:terminal
my-app
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
└── src
    ├── App.css
    ├── App.js
    ├── App.test.js
    ├── index.css
    ├── index.js
    ├── logo.svg
    └── serviceWorker.js
```
</div></details>

```sh:terminal
cd hello-react
yarn start
```

黒地に青色、好きな組み合わせです。緑キライ:dizzy_face:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294402/095a625c-3948-fe12-90da-72230c984613.png)

## 2nd: Hello World!
最終的には[jekyllで作ったGithubPages](https://oriverk.github.io)をNext.jsで作り直したいなと思ってますが、取り敢えず最初は『Hello, World!』でしょう。

```src/App.js
import React from 'react';

class App extends React.Component {
  render()
  {
    return (
      <div>
        <h1>Hello React World!</h1>
      </div>
    );
  }
}

export default App;
```
```sh:terminal
yarn start
```
出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294402/1137874e-4715-d02d-4521-bc9a65a45f14.png)

<details><summary>html側に出力されたもの</summary><div>

```html:html
<html lang="en"><head>
    <meta charset="utf-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="theme-color" content="#000000">
    <meta name="description" content="Web site created using create-react-app">
    <link rel="apple-touch-icon" href="/logo192.png">
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="/manifest.json">
    <!--
      Notice the use of  in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
  <style type="text/css">body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}
</style></head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"><div><h1>Hello React World!</h1></div></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  <script src="/static/js/bundle.js"></script><script src="/static/js/0.chunk.js"></script><script src="/static/js/main.chunk.js"></script>

</body></html>
```
</div></details>

なるほどね。たまに見かけるReact製ウェブサイトのhtmlコードと同じ感じ。

## 3rd: Counter
App.jsだけ修正

```src/App.js
import React, { Component } from 'react';

const App = () => {
  return <Counter />
}

class Counter extends Component
{
  constructor(props)
  {
    super(props);
    this.state = {
      value: 0
    }
  }

  onIncrement = () => {
    this.setState({ value : this.state.value + 1 });
  }

  onDecrement = () => {
    this.setState({ value: this.state.value - 1 });
  }
  render() {
    return (
      <div>
        <div>
          カウント値：{this.state.value}
        </div>
        <div>
          <button type='button' onClick={this.onIncrement}>+</button>
          <button type='button' onClick={this.onDecrement}>-</button>
        </div>
      </div>
    )
  }
}
export default App;
```
ほーん、これでいいのね。ちょっと理解した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294402/fd898140-a59d-5ba9-a8c7-eaed137213eb.png)

<details><summary>html側に出力されたもの</summary><div>

```html:html
<html lang="en"><head>
    <meta charset="utf-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="theme-color" content="#000000">
    <meta name="description" content="Web site created using create-react-app">
    <link rel="apple-touch-icon" href="/logo192.png">
    <link rel="manifest" href="/manifest.json">
    <title>React App</title>
  <style type="text/css">body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}
</style></head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"><div><div>カウント値：21</div><div><button type="button">+</button><button type="button">-</button></div></div></div>
    
  <script src="/static/js/bundle.js"></script><script src="/static/js/0.chunk.js"></script><script src="/static/js/main.chunk.js"></script><script src="/main.54b098efa41503c182ac.hot-update.js"></script>

</body></html>
```
</div></details>

### propsとは
[参照：コンポーネントと props from reactjs.org](https://ja.reactjs.org/docs/components-and-props.html#gatsby-focus-wrapper)
コンポーネント利用時に設定できるオブジェクトの値で、読み取り専用で、変更不可。
 
### stateとは
[参照：state とライフサイクル from react.js](https://ja.reactjs.org/docs/state-and-lifecycle.html)
- コンポーネント利用時に設定できるオブジェクトの値で、後から変更可能
    - stateの更新にはsetState()を使う
    - stateはコンストラクタを以外では直接代入してはいけない
        - 通常は ```this.setState({comment: 'hello'});``` と言った感じで。
    - stateの更新は非同期で行われる可能性がある
    - reactではstateが変更されたタイミングでコンポーネントの再描画を行う
        - UI変更に不要なプロパティはpropsで管理すべし