React 基礎知識から Props, useState, useEffect について

#学習の経緯
一番の理由はフロント側に興味津々で早く触りたいと思ってたためです。
また、周りで触っているエンジニアさんも多かったこともあり、**`React`**を習得することを決意。

##前提

- CodeSandboxを使用

https://codesandbox.io/

##JSX記法のルール

* **`JSX`とは**
    * JavaScript を拡張し、UI 要素を記述するのに HTML のようなタグ構文が使えるようにした**Javascriptの拡張構文**のこと
* コード説明(下記参照)
    * `import React from "react";`
        * React でコードを書くためのオマジナイ
    * `import ReactDom from "react-dom";`
        * HTML にコンポーネントを反映するための記述
    * `const App`
        * Hello! と Tom が出力される関数の定義
            * 複数要素の場合は、`return`を`()`で囲う必要がある
            * 且つ、 return する HTML の内容は１つのタグ(`<> </>`)で囲う必要がある
    * `ReactDom.render(<App />, document.getElementById("root"));`
        * 画面に反映させるための記述
        * 構文 : `ReactDom.render(関数等(element), 反映させる場所(container));`

```react:index.js
import React from "react";
import ReactDom from "react-dom";

const App = () => {
  return (
    <>
      <h1>Hello!</h1>
      <p>Tom</p>
    </>
  );
};

ReactDom.render(<App />, document.getElementById("root"));
```

##コンポーネント
**UIの一部分となるビュー(View)を切り出したもの。
また、単にUIを切り出すだけでなく、新たにコードを含むことも可能で、プログラムとして再利用できる。**

* `import React from "react";`
  * `React`でコードを書くためのオマジナイ
* `export default`
  * 記述することで他のファイルで使用することができる
* `xxx.jsx`
  * React のコンポーネント専用に用意されている拡張子
      * `xxx.js`でもエラーは起きないが、明示的に示すことができる

**【コンポーネントの作成その①】**

```react:src/App.jsx
import React from "react";

const App = () => {
  return <h1>Hello!</h1>
};

export default App;
```

- **`App.jsx`コンポーネントを使用するための記述**
 - import は**相対パス**で記述する(`"./App"`)

```react:src/index.js
import React from "react";
import ReactDom from "react-dom";
import App from "./App"; // 追加

ReactDom.render(<App />, document.getElementById("root"));
```

**【コンポーネントの作成その②】**

```react:src/App.jsx
import React from "react";

export const App = () => {
  return <h1>Hello!</h1>
};
```

* `export const App = () => {`
    * 関数コンポーネント前に`export`を記述する

```react:src/index.js
import React from "react";
import ReactDom from "react-dom";
import { App } from "./App";

ReactDom.render(<App />, document.getElementById("root"));
```

* `import { App } from "./App";`
    * インポートは、分割代入をして記述する

## 命名規則

- **ファイル名**・・・パスカルケースで記述する　
 - パスカルケース・・・先頭が大文字で始まり、単語の区切りを大文字とする記法のこと

```
○ App.jsx             ✕ app.jsx
○ SomeComponents.jsx  ✕ someComponets.jsx
```

- **HTMLのタグ内で扱うイベント名**・・・キャメルケースで記述する
 - キャメルケース・・・先頭が小文字で始まり、単語の区切りを大文字とする記法のこと

```
○ onClickButton  ✕ OnClickButton
                 ✕ on-click-button
```

##CSS(スタイル)の当て方

* **HTMLの要素にstyles.cssを適用**
    * `jsx`ファイルの場合、`class`ではなく、`className`とする

```react
<div className="クラス名">
```
     
* **HTMLの要素内に記述**
    * 値を記述する際の１つ目の`{ }`は、JavaScriptを記述するためのもので、２つ目の`{ }`は、オブジェクトを記述するためのもの
* プロパティーの値は必ず**ダブルコーテーション**`""`もしくは、**シングルコーテーション**`''`で囲うこと

```react
<h1 style={{ color: "red" }}>Hello!</h1>
```

- **変数に定義する**
 - スタイル名はキャメルケースで記述する

```
○ fontSize  ✕ font-size
```


```react
const App = () => {
  const contentStyle = {
    color: "blue",
    fontSize: "18px"
  };
  return <h1 style={contentStyle}>Hello!</h1>
```

##Props
**コンポーネントに渡す引数のようなもの**

* `components`ディレクトリ直下に、**コンポーネントファイル**を作成

■ **文字色とメッセージを渡すコンポーネントファイルの場合**
　・ 画面にHello！(青色)とTom(ピンク色)を表示

```react:src/components/ColorfulMessage.jsx
import React from "react";

const ColorfulMessage = (props) => {
  console.log(props); // {color: "blue", message: "Hello!"},
                      // {color: "pink", message: "Tom"}
  const { color, message } = props;
  const contentStyle = {
    color,
    message
  };
  return <h1 style={contentStyle}>{message}</h1>;
};

export default ColorfulMessage;
```

* `const ColorfulMessage = (props) => {`
    * 関数の引数`(props)`は、任意の文字でも問題ない(明示的にするため、`props`としている)
* `const { color, message } = props;`
    * 記述量を減らすため、分割代入している
    * しない場合、`<h1>`タグ内の`{message}`を`{props.message}`と記述する必要がある

```react:src/components/App.jsx
import React from "react";
import ColorfulMessage from "./components/ColorfulMessage";

const App = () => {
  return (
    <>
      <ColorfulMessage color="blue" message="Hello!" />
      <ColorfulMessage color="pink" message="Tom" />
    </>
  );
};

export default App;
```

* `<ColorfulMessage color="blue" message="Hello!" />;`
    * **コンポーネント名のタグ**を作成することでコンポーネントを使用することができる
    * `color="blue" message="Hello!"`
        * 動的に文字色とメッセージを変更するため、**プロパティー値**(`"blue"`と`"Hello!"`)を`ColorfulMessage`コンポーネントに渡している
        * porps名(`color`, `message`)は任意の文字を付けることができる

■ **親コンポーネントのタグにメーセージを記述する場合**
　・ 画面にHello！(青色)とTom(ピンク色)を表示

```react:src/components/ColorfulMessage.jsx
import React from "react";

const ColorfulMessage = (props) => {
  console.log(props); // {color: "blue", children: "Hello!"}
                      // {color: "pink", children: "Tom"}
  const { color, children } = props;
  const contentStyle = {
    color
  };
  return <h1 style={contentStyle}>{children}</h1>;
};

export default ColorfulMessage;
```
* `{children}`
    * 親コンポーネントのタグで囲んでいる要素を表示することができる
        * `<ColorfulMessage color="blue">Hello!←ココ</ColorfulMessage>`

```react:src/components/App.jsx
import React from "react";
import ColorfulMessage from "./components/ColorfulMessage";

const App = () => {
  return (
    <>
      <ColorfulMessage color="blue">Hello!</ColorfulMessage>
      <ColorfulMessage color="pink">Tom</ColorfulMessage>
    </>
  );
};

export default App;
```

##useState
**各コンポーネントが持つ状態のことで、画面上に表示されるデータ等を保持している状態を指す。**

* `State`が変更されると再レンダリングされる
    * 条件によって動的に変わる部分を定義することで、様々な状態の画面を表示することができる
    * 親コンポーネントが再レンダリングされた場合、**子コンポーネントも再レンダリングされる**

■ **値を動的に更新するクリックイベントの場合**
　・ ボタンをクリックする毎に`num`の値が +1 され、更新後の値が画面に表示される

```react:src/components/App.jsx
import React, { useState } from "react";

const App = () => {
  const onClickCountUp = () => {
    setNum(num + 1);
  };
  const [num, setNum] = useState(0);
  return (
    <>
      <button onClick={onClickCountUp}>カウントアップボタン</button>
      <p>{num}</p>
    </>
  );
};

export default App;
```

* `import React, { useState } from "react";`
    * useState を使用するため、分割代入で取り出している
* `const [num, setNum] = useState(0);`
    * 構文 : `const [<stateとして使用する変数名>, <値を更新するための関数名>] = useState(<初期値>);`
* `setNum(num + 1);`
    * 設定したい値を記述する

■ **要素を表示/非表示させるクリックイベントの場合**
　・ ボタンをクリックすると、要素の値が`false`になることで非表示になり、再度クリックすると、要素の値が`true`になり Hello! が表示される（表示/非表示の繰り返し）

```react
import React, { useState } from "react";

const App = () => {
  const [showFlag, setShowFlag] = useState(true);
  const onClickGreeting = () => {
    setShowFlag(!showFlag);
  }
  return (
    <>
      <button onClick={onClickGreeting}>on/off</button>
      <p>{showFlag && "Hello!"}</p>
    </>
  );
};

export default App;
```

* `setShowFlag(!showFlag);`
    * 変数の先頭に`!`を付けることで、要素の値を切り替えている
* `<p>{showFlag && "Hello!"}</p>`
    * showFlag が true の場合、 Hello! が表示されるように論理演算子を使用している

##useEffect
**レンダリングと副作用を切り離すことができる。
そのため、関数の実行タイミングをレンダリングされるまで遅らせることができる。**

■ **カウントアップボタンをクリックし、3 の倍数時のみ、 Hello! を表示させ、且つ、on/offボタンのクリックイベントも反映させている場合**

[![Image from Gyazo](https://i.gyazo.com/802c4cb1344fef77c016e2a03779e9ae.gif)](https://gyazo.com/802c4cb1344fef77c016e2a03779e9ae)

```react
import React, { useEffect, useState } from "react";

const App = () => {
  const [num, setNum] = useState(0);
  const [showFlag, setShowFlag] = useState(false);
  const onClickCountUp = () => {
    setNum(num + 1);
  };
  const onClickGreeting = () => {
    setShowFlag(!showFlag);
  };

  useEffect(() => {
    if (num > 0) {
      if (num % 3 === 0) {
        showFlag || setShowFlag(true);
      } else {
        showFlag && setShowFlag(false);
      }
    }
  }, [num]);

  return (
    <>
      <button onClick={onClickCountUp}>カウントアップボタン</button>
      <p>{num}</p>
      <button onClick={onClickGreeting}>on/off</button>
      <p>{showFlag && "Hello!"}</p>
    </>
  );
};

export default App;
```

* `import React, { useEffect, useState } from "react";`
    * useEffect を使用するため、分割代入で取り出している
* `if (num > 0) {`
    * num の値が 0 以上の場合に表示させるための条件分岐
* `showFlag || setShowFlag(true);`
    * showFlag が　false の場合のみ、setShowFlag(true) を実行
        * setShowFlag(true) のみの記述の場合、state が必ず呼び出されることで再レンダリングされてしまい、**「無限ループが起きてしまうから気をつけて」**というエラーが表示される
* `showFlag && setShowFlag(false);`
    * showFlag が true の場合、setShowFlag(false)　を実行
* `  }, [num]);`
    * useEffect の**第引数の配列**に num を指定することで num の値が更新された場合のみ、実行させるように制御することができる

##終わりに
触ってみた感想として、とても魅力的な言語だと感じました（語彙力とは）　
これからも継続的に学習していきます。
     
##参考教材

https://www.udemy.com/course/modern_javascipt_react_beginner/