Reactについて学んだことをまとめる

以下のUdemyの講座を受講したので、Reactについて学んだ事をまとめる。

https://www.udemy.com/course/modern_javascipt_react_beginner/?couponCode=KEEPLEARNING

## Reactの要素

### JSX(JavaScript XML)記法
ReactはJSX記法を用いてコードを記述する。
JavaScriptの中にHTMLのような形でコードを書くことができる。
```
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';

const rootElement = document.getElementById('root');
const root = createRoot(rootElement);

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

root.render(
  <StrictMode>
    <AppHoge /> 
  </StrictMode>
);
```

### コンポーネント
Reactでは、主にコンポーネントに表示する内容を記述し、HTMLのタグのように取り扱うことができる。
画面の要素の使いまわしが容易になる。
コンポーネントはJavaScriptのアロー関数の形で定義する。
**コンポーネントの名前はパスカルケース(単語の先頭を大文字にしてつなげる)で記述**する。
また、**コンポーネントが返す内容は1つのタグで囲まれていないといけない**。
`<>`,`</>`は画面に反映されず、エラー回避のために用いられる？
```
// コンポーネント
const AppHoge = () => {
  return (
    <>
	  <h1>Hello!</h1>
	</>
  );
};

root.render(
  <StrictMode>
    <AppHoge /> 
  </StrictMode>
);
```

コンポーネントを別ファイルに切り出す場合は、拡張子を`.jsx`とし、
`export`を用いることで別ファイルから参照が可能となる。
```
// component.jsx
// コンポーネントのエクスポート
export const App = () => {
  return (
    <>
	  <h1>Hello!</h1>
	</>
  );
};
```

他のファイルを参照する場合は、`import`を用いる。
```
//main.jsx

import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { App } from "./component"

const rootElement = document.getElementById('root');
const root = createRoot(rootElement);

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

root.render(
  <StrictMode>
    <App /> 
  </StrictMode>
);
```

### イベントとスタイル
ボタンなどのイベントを記述する際にJavaScriptで記述できる。
**`{}`で囲まれた部分はJavaScriptのコードとして解釈**される。

スタイルはJavaScriptのオブジェクトとして記述できる。
スタイル要素の名称はハイフンを取り除き、キャメルケース(単語の先頭を大文字にしてつなげる、ただし最初の単語の先頭のみ小文字)で記述する。
```
export const app = () => {
  const onClickButton = () => alert();
  const contentStyle = {
    color: "blue",
    fontSize: "18px"
  }
  return (
    <>
      <h1 style={contentStyle}>てすと</h1>
	  <button onclick={onClickButton}ボタン</button>
	</>
  );
};
```

### Props
コンポーネントに渡す引数。
Propsを渡す方法は、タグの属性を用いる方法と、開始タグ・終了タグで囲まれた値を渡す方法がある。
```
// component.jsx

// colorとmessageの属性に指定した値を受け取れる
export const ColorfulMewsageA = (props) => {
  const contentStyleA = {
    color: props.color
  };
  
  return <p style={contentStyleA}>{props.message}</p>;
};

// 開始タグと終了タグに囲まれた値はchildrenで取得できる
export const ColorfulMewsageB = (props) => {
  const contentStyleB = {
    color: props.color
  };
  
  return <p style={contentStyleB}>{props.children}</p>;
};


//main.jsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { App } from "./component"

const rootElement = document.getElementById('root');
const root = createRoot(rootElement);

const App = () => {
  return (
    <>
	  <ColorfulMessageA color="red" message="Hello!" /> //属性で渡す
	  <ColorfulMessageB color="blue">Hellooooooo!</ColorfulMessageB> //開始タグと終了タグで渡す
	</>
  );
};

root.render(
  <StrictMode>
    <App /> 
  </StrictMode>
);
```

### State
コンポーネントが持っている状態はStateで管理する。
コンポーネントの変数みたいなもの。
`State`を定義する際は、`useState`を使用する。
`useState()`は`State`と`State`を更新する関数を返し、
useStateの第1引数に値を渡すと、`State`の値を第1引数に渡された値で初期化する。
```
const [num, setNum] = useState(初期値);

例:
//main.jsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { App } from "./component"

const rootElement = document.getElementById('root');
const root = createRoot(rootElement);

const App = () => {
  const [num, setNum] = useState(0);
  const onClickCountUp = () => {
    setNum(num + 1);           // 関数の最後にまとめて実行される
    setNum((prev) => prev + 1) // 引数prevにはStateの現在の値が渡される。
  };

  return (
    <>
      <button onClick={onClickCountUp}カウントアップ</button>
	  <p>{num}</p>
	</>
  );
};

root.render(
  <StrictMode>
    <App /> 
  </StrictMode>
);
```

注意点として、`set`関数は呼び出された関数の最後にまとめて実行される。
実行が予約されるイメージ。
また、`set`関数は引数に関数を受け取ることができる。
引数で渡した関数は引数を取ることができ、その引数にはStateの現在の値が渡される。

`useState`はコンポーネントの一番上の階層でしか呼ぶことができない。

### 再レンダリングと副作用
以下の場合に画面の再レンダリングが発生する。
- Stateが更新された時
- Propsを受け取っているコンポーネントのPropsが更新された時
- 親コンポーネントが再レンダリングされると、子コンポーネントが再レンダリングされる。

再レンダリングが発生した場合、そのコンポーネントを頭から再評価する。
それにより意図せず他の変数に影響を与えてしまう場合がある。
`useEffect`というフックを使用すると、特定の変数に変更があった場合のみ実行する関数を記述することができる。

`useEffect`の第1引数に実行したい関数を記述する。
`useEffect`の第2引数に空配列を指定すると、マウント時(ページが最初に読み込まれる時)に1度だけ実行される。
第2引数の配列要素に変数を指定すると、指定した変数が更新された場合に第1引数に記述した関数が実行される。
```
useEffect(() => num + 1, [num]) // 変数numが更新されると第1引数の関数が呼ばれる
```


## Reactの注意点や気付き
- Reactではタグでクラスを指定する際に「class」ではなく「className」を使用する。

- ループしながら配列の内容を取り出して処理する際は`map`を使う。
  `map`などでループして処理する場合は、`return`する頭の要素に`key`を指定する必要がある。
  `key`はループで処理する際、一意になる値を指定する。

- Reactでイベントを発火した際は`event`という`Prop`に発火した際の情報が格納される。
  `event.target.value`でテキストボックスに入力された内容を取得できる。

- `onclick`等のイベントに対し、引数を伴う関数を指定する場合は、
  アロー関数として引数を伴う関数を実行する関数を定義する。
  ｛｝で囲まれているので単純な関数の実行として解釈されてしまう。

- `set`関数を使って更新する場合は、新しい配列を作成した上で渡す。

- コンポーネント化する場合は、関数はコンポーネントに切り出さず、
  `Props`で関数をコンポーネントに渡す方がスマートになる場合がある。

- スタイルは、コンポーネントで閉じている方が管理しやすいので、
  グローバルなcssで定義するのではなく、コンポーネント化したファイル内で管理する方が良い。