React きほんとか雑多なめも

React の基本とか雑多なメモを発散
環境構築（Win11）とか簡単な準備は以下にまとめてる感じなので参考までに．．．

https://qiita.com/sueasen/items/5aaac3dd4052de82c2f9

https://qiita.com/sueasen/items/99b25098823d966f1135

# JSX(React で使うJavaScript 構文拡張機能)

React ドキュメントより引用 https://react.dev/learn/writing-markup-with-jsx
> JSX は、JavaScript ファイル内に HTML のようなマークアップを記述できるようにする JavaScript の構文拡張機能です。コンポーネントを記述する他の方法もありますが、ほとんどの React 開発者は JSX の簡潔さを好み、ほとんどのコードベースは JSX を使用します。

### JSXルール：単一のルート要素を返す
コンポーネントから複数の要素を返すには、それらの要素を 1 つの親タグでラップします。
良く使うやり方として `retrun` するときは1つの空タグ `<>・・・</>` で囲う
```JSX
const App = () => {
  return (
    <>
      <h1>Hellow World</h1>
      <p>aaa bbb ccc</p>
      <ul>
        ...
      </ul>
    </>
  );
};
```
### JSXルール：JavaScript  `{ ・・・ }` で囲って書く
イベントなどで関数を呼ぶときなど JavaScript で記載します
```JSX
const App = () => {
  return (
    <>
      <h1>Hellow World</h1>
      <p>aaa bbb ccc</p>
      <button onClick={() => alert('aaa ddd')}>aaa</button>
    </>
  );
};
```
### 参考：条件分岐
基本的にはJavaScriptと同じでかけるがその場で出力するように書く
複雑に条件分岐したい場合はメソッドするなどした方が良さそう
例として3パターンを記載
- 単純に条件が true の時 `&&` 使う
```JSX
const App = () => {
  const condition = true;
  return (
    <>
      {condition && <p>trueの場合</p>}
    </>
  );
};
```
- 三項演算子演算子
```JSX
const App = () => {
  const condition = true;
  return (
    <>
      {condition ? <p>trueの場合</p> : <p>falseの場合</p> }
    </>
  );
};
```
- null, undefined の時 `??` 使う
```JSX
const App = () => {
  const condition = undefined;
  return (
    <>
      {condition ?? <p>null, undefinedの場合</p>}
    </>
  );
};
```
### 参考：繰り返し
条件分岐と同じで基本的にはJavaScriptと同じでかけるその場で出力するように書く
複雑に処理したい場合はメソッドするなどした方が良さそう
React で key 設定しないと警告でるので設定する（keyがないと差分更新できないなどパフォーマンスに影響）
- 配列から新しい配列生成する `map` 使う
```JSX
const App = () => {
  const array = [1, 2, 3, 4, 5];
  return (
    <>
      {array.map(v => <p key={v}>{v}</p>)}
    </>
  );
};
```
### 参考：複数行のJavaScript記載
JSX内で複数行のJavaScript記載する方法を念のため記載
念押しで．．．複雑に処理したい場合はメソッドするなどした方が良さそう．．．
- `(...)` で関数を囲って `()` つけて即時実行でその場に出力
```JSX
const App = () => {
  const array = [1, 2, 3, 4, 5];
  return (
    <>
      {(() => {
        const condition2 = undefined;
        if (condition) {
          return <p>trueの場合</p>;
        } else {
          return <p>falseの場合</p>;
        }
      })()}
    </>
  );
};
```


# export・import

React というか JavaScript でモジュールにする方法
React ではコンポーネントなどファイル分割しながら開発するので `export`, `import` が必要になる
作成したコンポーネントや定義、メソッドを他のファイルで使えるようにするのが `export` する
React のモジュール(メソッド)や作成したコンポーネントなどを使う時は `import` する
`export` に以下の2つの方法があり使い方に違いがある

- `default export` (1ファイル1定義)
- `named export` (1ファイル複数定義)

## default export (1ファイル1定義)

特徴としてはこんな感じ
- 1ファイルで1つだけ `export` できる
- `import` するときに名前を自由に定義できる

使い方はこんな感じ
- `export` は基本的にファイル名で定義してファイルの最後に `export default` を記載
- `import` は `import 定義名 from 'ファイルパス'` を記載

```jsx:default export Sample.js
// const で ファイル名を使って定義 (ファイル名でなくてもOKだけどファイル名にするのが基本)
const Sample = () => {
  return <h1>サンプル</h1>
}
// ファイルの最後に export default ファイル名
export default Sample
```
```jsx:default export の import
// import 定義名 from ファイルパス で定義
import Sample from './Sample'
// 定義名 は import 時に変えてもOK（↓でも使える）
import Sample2 from './Sample'
import ASample from './Sample'
```

## named export (1ファイル複数定義)

特徴はこんな感じ
- 1ファイルで複数 `export` できる
- `import` するときに名前は `export` した名前で定義になる

使い方はこんな感じ
- `export` は `export const 定義名 = ...` で記載
- `import` は `import {定義名1, 定義名2, ...} from 'ファイルパス' ` で記載

```jsx:named export Sample.js
// export const で 定義
export const sample1 = () => {
  return <h1>サンプル1</h1>
}
// export const で複数定義できる
export const sample2 = () => {
  return <h1>サンプル2</h1>
}
```

```jsx:named export の import
// import {定義名1, 定義名2, ...} from ファイルパス で定義
import {sample1, sample2} from './Sample'
// 使いたい定義だけで OK
import {sample1} from './Sample'
```


# コンポーネント作成

React ではコンポーネント（主に画面の部品）ごとに作るので基本的な文法
タグを返すファンクションを作ってそれを export することで他から使えるようになる
export するときの名前はファイル名にする

- コンポーネント 1タグ
```JSX:App.js
// コンポーネント定義（タグを返すファンクション）
const App = () => <h1>Hello World</h1>;
// export して他から使えるようにする
export default App;
```
- コンポーネント定義 複数タグ
```JSX:App.js
// コンポーネント定義（タグを返すファンクション）
const App = () => {
  // 複数タグは return を空タグで囲って1つにまとめる
  return (
    <>
      <h1>Hello World</h1>
      <p>App.jsx</p>
    </>
  );
};
// export して他から使えるようにする
export default App;
```

# DOMと紐づける（HTMLのタグにレンダリング）

`ReactDOM` を使ってReactの仮想DOMをブラウザに反映（レンダリング）させる
ライブラリ、コンポーネントを import してDOMと紐づけた仮想DOMにコンポーネントをレンダリングする
React では基本的に HTML に一つだけタグ用意してそれにコンポーネントをレンダリングして画面構築
create-react-app などでは index.js で HTML に用意したタグを使ってやっている

- import (ライブラリ、コンポーネント参照)
```JSX:index.js
import ReactDOM from 'react-dom/client'; // ReactDOM
import App from './App';                 // コンポーネント（自分で作った jsx など）

// 仮想DOM生成（仮想DOM と DOM 紐づけ）
const root = ReactDOM.createRoot(document.getElementById('root'));
// コンポーネントレンダリング
root.render(<App />);

// コンポーネントを複数レンダリングしたいときは空タグで一つでまとめる
// root.render(
//   <>
//     <App />
//     <App />
//     <Compornent1 />
//       ・
//   </>
// );
```

# イベント定義

コンポーネントの中でイベントのファンクションを定義
JSXの中ではタグの要素として `{ イベントファンクション定義名 }` でファンクションを設定できる

```JSX:App.js
const App = () => {
  // イベント定義 引数なし
  const onClickBtn1 = () => {
    alert('aaa bbb');
  };
  // イベント定義 引数あり
  const onClickBtn2 = (arg) => {
    alert(arg);
  };

  return (
    <>
      <h1>Hello World</h1>
      // 引数なし の呼び出しはそのまま、またイベント使いたいときもこれでOK
      <button onClick={onClickBtn1}>button1</button>
      // 引数あり の呼び出しは2パターン、bind で設定 or 関数でラップ、イベント使う時はラップが良さそう
      <button onClick={onClickBtn2.bind(null, 'arg aaa bbb')}>button2</button>
      <button onClick={() => onClickBtn2('arg aaa bbb')}>button2</button>
    </>
  );
};

export default App;
```

# 簡易なスタイル設定（要素に直書き）

コンポーネントにスタイルをあてる一番、簡易な方法
スタイルをJSONで定義
JSXの中ではタグの要素として `{ スタイル定義名 }` でスタイルを設定できる
スタイルに直接書いてもOK

```JSX:App.js
const App = () => {
  // スタイル定義
  const styles = {
    color: 'red',     // プロパティ値は文字列として '' などで括る必要あり
    fontSize: '20px', // プロパティ名はキャメルケースになる font-size → fontSize
  };

  return (
    <>
      // 宣言した styles を style に設定
      <h1 style={styles}>Hello World</h1>
      // styles に直接書いてもOK
      <h1 style={{color:'red', fontSize:'20px'}}>Hello World</h1>
    </>
  );
};
```

# Props (コンポーネントの引数)

React でコンポーネントに渡す引数として Props がある
コンポーネントを作るときに props を引数として受け取るように定義
コンポーネントを使う時にタグの要素として値を設定


簡単な色、サイズを指定するテキストのコンポーネントを例にしてやってみる
例では `./src/components` に作ってます 

## Props の基本的な使い方
コンポーネントでは引数に `props` を定義して `props.属性名` で値を取得
コンポーネントを使う時に `<コンポーネント 属性名=値 .. />` で渡す値を設定

- コンポーネントの作成
```JSX:ColorText1.js
// 引数として props を定義、値は props.要素名 で取得
const ColorText1 = (props) => {
  const styles = {
    color: props.color,
    fontSize: props.fontSize,
  };

  return (
    <>
      <p style={styles}>{props.text}</p>
    </>
  );
};

export default ColorText1;
```

- 作ったコンポーネントを使う
```JSX:App.js
// コンポーネントをインポート
import ColorText1 from './components/ColorText1';

const App = () => {
  return (
    <>
      {/* タグの要素名 をコンポーネント側と合わせて値を設定 */}
      <ColorText1 color="blue" fontSize="20px" text="適当に．．．" />
    </>
  );
};

export default App;
```

## Props の children を使う

コンポーネントのタグの中に入れた要素をコンポーネントで使う時に children を使う
children を使うとコンポーネントやタグなどを引数に設定できたりと色んな使い方ができる
コンポーネントでは `props.children` で値を取得
コンポーネントを使う時は `<コンポーネント>childrenに設定する要素、値</コンポーネント>`で設定

- コンポーネントの作成
```JSX:ColorText2.js
const ColorText2 = (props) => {
  // props に任意の属性を設定して併用はOK
  const styles = {
    color: props.color,
    fontSize: props.fontSize,
  };
  
  return (
    <>
      {/* props.children で値を取得 */}
      <p style={styles}>{props.children}</p>
    </>
  );
};

export default ColorText2;
```

- 作ったコンポーネントを使う
```JSX:App.js
import ColorText2 from './components/ColorText2';

const App = () => {
  return (
    <>
      {/* 開始タグ、終了タグで囲って値を設定 */}
      <ColorText2 color="blue" fontSize="50px">
        <li>適当に．．．</li>
      </ColorText2>
    </>
  );
};

export default App;
```

## Props の分割代入(Destructuring Props)
コードを読みやすく理解しやすくするため props を分割代入することがある
TypeScript だと型定義になるけど簡易的な方法として．．．

- 処理の最初に分割代入
```JSX:ColorText1.js
const ColorText1 = (props) => {
  // props から分割代入（変数名を属性名にして取得）
  const { color, fontSize, text } = props;
  const styles = {
    color,     // color: color と同じこと
    fontSize,  // fontSize: fontSize と同じこと
  };

  return (
    <>
      <p style={styles}>{text}</p>
    </>
  );
};

export default ColorText1;
```

- 引数の定義で分割代入
```JSX:ColorText2.js
// 引数の定義で分割代入（変数名を属性名にして取得, children も使える）
const ColorText2 = ({color, fontSize, children}) => {
  const styles = {
    color,     // color: color と同じこと
    fontSize,  // fontSize: fontSize と同じこと
  };

  return (
    <>
      <p style={styles}>{children}</p>
    </>
  );
};

export default ColorText2;
```

# useState (React Hooks の1つ、コンポーネントの状態管理)

画面など動的に変えたいものを変数として管理するのに `useState` を使う
`useState` をインポートして `useState` の戻り値の 状態変数と更新ファンクションを使って処理をしていく

```JSX:App.js
// useState をインポート
import { useState } from 'react';

const App = () => {
  // [状態管理する変数名, 変数更新用のファンクション] = useState(初期値)
  const [count, setCount] = useState(0);

  const onClickBtn = () => {
    // 変数更新用のファンクションを使って値を設定(更新)
    setCount((count) => count + 1); // setCount(count + 1) でもOK
  };

  return (
    <>
      <button onClick={onClickBtn}>count up</button>      
      <p>{count}</p>
    </>
  );
};

export default App;
```

# useEffect (React Hooks の1つ、変更時の処理設定)

値などに変更があった際に処理を実行したいときに `useEffect` を使う
`useEffect` をインポートして `useEffect` に変更時の処理と変更を監視する変数を引数（配列）に渡す


```JSX:App.js
// useEffect をインポート、from が同じ時はまとめて記載できる
import { useState, useEffect } from 'react';

const App = () => {
  const [count, setCount] = useState(0);
  const [countRet, setCountRet] = useState();

  // useEffect(変更時の処理, [変更を監視する変数, ...複数OK, 空配列にすると初回だけ]
  useEffect(() => setCountRet('count ret:' + count), [count]);

  const onClickBtn = () => {
    setCount((count) => count + 1);
  };

  return (
    <>
      <button onClick={onClickBtn}>count up</button>
      <p>{count}</p>
      <p>{countRet}</p>
    </>
  );
};

export default App;
```

# useContext (React Hooks の1つ、コンポーネント間のデータ共有)

コンポーネント間でデータを共有したいときに `useContext` を使う
`createContext`, `useContext` をインポートして `createContext` でデータ共有する `context` (格納する箱) を作って `Context.Provider` で値を提供し `useContext` で値を受け取る
`context` を管理するコンポーネントを作成して `provider`(値を設定する), `consumer`(値を受け取る) を作って操作することが多い

簡単な例としてカウントアップする値をやり取りするコンポーネントを以下のような関係でやってみる

- `context`管理するコンポーネント `SampleContext.js`
  - `/src/contexts` ディレクトリの下に作る
- `context` から値を取得するコンポーネント `SampleGet.js`
  - `/src/components` ディレクトリの下に作る
- `context` に値を設定するコンポーネント `App.js`

## `context`管理するコンポーネント `SampleContext.js`
- `context` を `createContext` で作成する
- `SampleContextProvider` を `export` する
  - 提供する値の設定(`Context.Provider`)と使える範囲を囲う 
- `SampleContextConsumer` を `export` する
  - 値を受け取る(`useContext`)
```JSX:SampleContext.js
// createContext, useContext をインポート 
import { createContext, useContext } from 'react';

// context (データ格納する箱) を作る
const SampleContext = createContext();

// Provider で値を設定, データ共有は Provider で囲った範囲
export const SampleContextProvider = ({ values, children }) => {
  return (
    <SampleContext.Provider value={{ values }}>
      {children}
    </SampleContext.Provider>
  );
};

// useContext で値を受け取る, Provider で囲った範囲で使う必要あり
export const SampleContextConsumer = () => {
  return useContext(SampleContext);
};
```

## `context` に値を設定するコンポーネント `App.js`
`SampleContext.js` の `Provider` を使って値を設定して提供する
```JSX:App.js
// コンポーネントをインポート
import { SampleContextProvider } from './contexts/SampleContext';
import SampleGet from './components/SampleGet';

const App = () => {
  // Provider に設定するカウントアップする値
  const [num, setNum] = useState(1);

  return (
    <>
      // Provider に提供する値として num を values に設定
      <SampleContextProvider values={num}>
        <button onClick={() => setNum(num + 1)}>切り替え</button>
        <SampleGet />
      </SampleContextProvider>
    </>
  );
};

export default App;
```

## `context` から値を取得するコンポーネント `SampleGet.js`
`SampleContext.js` の `Consumer` を使って値を受け取る
```JSX:SampleGet.js
// SampleContext から SampleContextConsumer をエクスポート
import { SampleContextConsumer } from '../contexts/SampleContext';

const SampleGet = () => {
  // 値を受け取って使う
  const { values } = SampleContextConsumer();
  return <p>{values}</p>;
};
export default SampleGet;
```

# CSS適用

React のCSS適用に関してはいくつか方法があるが大きく分けて2つある
- CSSファイルに分けて書く方法 (CSS Modules, CSSファイル読込(ページ全体))
- JSファイル内に書く方法（CSS-in-JS (Inline styles, styled components etc...）

この記事では上の CSSファイルに分けて書く方法として2つのパターンをやってみる
またCSS拡張言語のSASS適用 と Tailwind CSS 適用もやってみる

- SASS(CSS拡張言語)適用
- CSSファイル読込(ページ全体)
- CSS Modules(コンポーネント内)
- Tailwind CSS 適用

## SASS(CSS拡張言語)適用

React, Vue などで良く使われるCSS拡張のSASS を使えるようにする
使えるようにするといってもインストールするだけです（2023/8/31だと ^7.0.3）
変数, ネスト構文 とか使えるのが便利なところかと、でも CSS でも変数, ネスト構文とか使えるようになってきてる．．．
公式ドキュメント https://sass-lang.com/documentation/ 

### インストール
```PowerShell
npm i node-sass
```

※ インストール時にエラーあった時の対処方をいくつか
- node-sass のバージョンを指定してインストール
  - node が v18.17.1 だと node-sass は v8.0.0 にすると良い(v7.0.3だとエラーになった)
  - `npm i node-sass@8.0.0` でバージョン指定してインストール実行する
  - node とのバージョンは以下を参照
      - https://www.npmjs.com/package/node-sass
- python が無くてエラー
  - python をインストールしてパスを通してあげると解決する
  - node が v18.17.1 だと python は v3.1.1 が良さそう (v3.1.2だとエラーになった)

### SASS構文
- 変数定義
```scss
// $変数名: 値 で定義
$font-family: 'Segoe UI', 'Roboto', 'Oxygen', 'Helvetica Neue', sans-serif;

body {
  // $変数名 で使う
  font-family: $font-family;
}
```

- ネスト構文
```scss
// { } の中に { } を書いてスタイル定義
.class_a {
  &:hover {
    font-size: 11px;
  }
  div {
      background-color: #000;
      font-size: 99px;
  }
  p {
    font-size: 88px;
  }
}
```

## CSS ファイル読込(ページ全体)

まずはページ全体へのCSSファイル適用をやってみる
コンポーネントではなくページ全体にCSSファイルの定義が反映される
index.js などで全体に関わる CSS 定義を設定するときに使える
コンポーネントで使うと変な感じになりそう．．．
CSSファイルを作ってJS側のファイルで import をするとき from がいらない
CSSファイル自体は通常のルールで定義する

- src/index.scss 作成
いったん全体のフォント設定の定義
```scss:index.scss
$font-families: BlinkMacSystemFont,Roboto,"Segoe UI","Helvetica Neue",HelveticaNeue,YuGothic,"Yu Gothic Medium","Yu Gothic",Verdana,Meiryo,sans-serif;

body {
  font-family: $font-families;
}
```

- src/index.js で読み込み
```jsx:index.js
import ReactDOM from 'react-dom/client';
// import が他と少し違う（from がない）
import './index.scss';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

```

## CSS Modules(コンポーネント内)

コンポーネント内のみにCSSファイルを適用する方法をやってみる
コンポーネントに閉じて定義できるので他への影響を考えないで良い反面、統一感がなくなる可能性がある．．．
CSSファイルの名前は `コンポーネントファイル名.module.scss(css)` にするのが一般的である
VSCode だと拡張機能 `open-css-module` を入れると自動生成みたいな感じにできる
CSSの定義するときはクラスセレクタで定義する必要がある（定義するトップ階層のみ、子階層はタグとかも使える）
コンポーネントの JS ファイルで import してCSS適用したいところにクラス名を設定する

### VSCode 拡張機能 open-css-module インストール・設定

拡張機能の open-css-module のを入れると良さそう
JSファイル作ったあとに `ctrl` + `shift` + `p` で `Open Css Module File` で import とファイルができあがる
拡張機能のページ念のため [open-css-module - Marketplace](https://marketplace.visualstudio.com/items?itemName=yasan.open-css-module)

- [拡張機能] - 検索ボックスに `open-css-module` 入力 - [インストール] でインストール
- [歯車アイコン] - [拡張機能の設定] で設定を開いて確認・更新
  - [Auto Create] のチェックボックスをチェック状態にする
  - [Styles Directory] のテキストボックスに `../styles/` にする

### サンプルコード
- src/styles/CssModules.module.scss
```scss:CssModules.module.scss
.container {
    border: solid 1px #aaa;
    border-radius: 20px;
    padding: 8px;
    margin: 8px;
    display: flex;
    justify-content: space-around;
    align-items: center;

    button {
        background-color: #ddd;
        border: none;
        padding: 8px;
        border-radius: 8px;

        &:hover {
            background-color: #aaa;
            color: #fff;
            cursor: pointer;
        }
    }
}

.title {
    margin: 0;
    color: #aaa;
}
```
- src/components/CssModules.js
```jsx:CssModules.js
// CSSファイルをインポート
import styles from '../styles/CssModules.module.scss';

const CssModules = () => {
  return (
    <>
      <div className={styles.container}>
        <p className={styles.title}>CSS Modulesです</p>
        <button>ボタン</button>
      </div>
    </>
  );
};

export default CssModules;
```

## Tailwind CSS 適用

CSSフレームワークとして Tailwind CSS を入れてみる
クラスで設定していく CSSフレームワーク
公式のページを参考 [tailwindcss.com 公式サイト create-react-app適用](https://tailwindcss.com/docs/guides/create-react-app) にしてます

### Tailwind CSS インストール
作ったプロジェクトに移動して以下のコマンド実行
```powershell
npm i tailwindcss
```

#### VSCode拡張機能 Tailwind CSS IntelliSense インストール
VSCode を使ってる場合、拡張機能の `Tailwind CSS IntelliSense` を入れると良さそう
コード補完とかしてくれるようになる
公式ページのリンク [Tailwind CSS IntelliSense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss
)
- [拡張機能] - 検索ボックスに `Tailwind CSS IntelliSense` 入力 - [インストール] でインストール

### Tailwind CSS 設定ファイル作成
続けて以下のコマンド実行
```powershell
npx tailwindcss init
```

### Tailwind CSS 設定ファイル編集
プロジェクト直下に `tailwind.config.js` が作らるので開いて `content` の設定を追加
```javascript:tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  // content の設定を追加
  content: ['./index.html', './src/**/*.{js,jsx,ts,tsx}'],
  theme: {
    extend: {},
  },
  plugins: [],
};
```

### CSS ファイルに Tailwind CSS 追加
ページ全体用の CSS を作って Tailwind CSS を追加する
例として `index.scss` に追加してます
```scss:index.scss
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
```

### サンプルコード
- components/TailwindCss.js
```javascript:TailwindCss.js
const TailwindCss = () => {
  return (
    <div className="border border-gray-400 rounded-2xl p-2 m-2 flex justify-around items-center">
      <p className="m-0 text-gray-400">Tailwind CSSです</p>
      <button className="bg-gray-300 border-0 p-2 rounded-md hover:bg-gray-400 hover:text-white">
        ボタン
      </button>
    </div>
  );
};
export default TailwindCss;
```

#### Tailwind CSS の VSCode 警告対応
公式ドキュメントにある以下の記載だと VSCode で警告が出てしまうことが．．．
念のためその対処方法を2つ記載
```scss
@tailwind base;       // Unknown at rule @tailwindscss(unknownAtRules)
@tailwind components;
@tailwind utilities;
```

<details><summary>CSS拡張設定追加</summary>

プロジェクトに `.vscode` フォルダを作ってその中に `settings.json`、`css_custom_data.json` を作成
`settings.json`、`css_custom_data.json` に以下の記載を追加
```json:settings.json
  "css.customData": [".vscode/css_custom_data.json"]
```
```json:css_custom_data.json
{
  "version": 1.1,
  "atDirectives": [
    {
      "name": "@tailwind",
      "description": "Use the @tailwind directive to insert Tailwind's `base`, `components`, `utilities`, and `screens` styles into your CSS."
    }
  ]
}
```

</details>

<details><summary>lint ルール無視追加</summary>

プロジェクトに `.vscode` フォルダを作ってその中に `settings.json` を作成
`settings.json` に以下の記載を追加
```json:settings.json
  "scss.lint.unknownAtRules": "ignore"
```
</details>

# 再レンダリングの最適化
React のコンポーネントは状態が変わると再レンダリングが行われる
コンポーネントがコンポーネントを持つ親子関係の場合、親のコンポーネントの再レンダリングで変更のない子コンポーネントも再レンダリングすることになる
その再レンダリングを最適化する方法として`memo`, `useCallback`, `useMemo` がある
過度な再レンダリングが発生するとパフォーマンスが悪化することがるの必要に応じて対応する

## `memo` コンポーネント `props` の変更による再レンダリング抑制
コンポーネントを `memo` でラップすることで再レンダリングを最適化することができる
`props` などが変更ない限り親コンポーネントに変更があっても再レンダリングしなくなる
使用する親コンポーネントは何も変更しないでOK
```jsx:Sample.js
// memo をインポート
import { memo } from 'react';

const Sample = (props) => {
  return (
    <>
      <p>tekito {props.val1}</p>
      {/* ・・・ */}
    </>
  );
};
// export するときに memo でラップするだけ
export default memo(Sample);
```

## `useCallback` `props` に設定する関数をキャッシュして固定化
`memo` を使用することで再レンダリングを抑制することができるが `props` に関数を設定すると常に変更した扱いになるため再レンダリングがおきてしまう
設定する関数を `useCallback` でキャッシュにすることで同じものが使われるようになり再レンダリングを抑制できる
親コンポーネントで設定する関数を `useCallback` の戻り値にして子コンポーネントは `memo` でラップすればOK  
```jsx:Sample.js
// memo をインポート
import { memo } from 'react';

const Sample = ({ onClickFunction }) => {
  return (
    <>
      <button onClick={onClickFunction}>click me</button>
      {/* ・・・ */}
    </>
  );
};
// export するときに memo でラップするだけ
export default memo(Sample);
```
```jsx:App.js
// useCallback をインポート
import { useState, useEffect, useCallback } from 'react';
import Sample from './components/Sample';

const App = () => {
  // 関数を useCallBack で生成 (第2引数に変数を渡すと値変更で再レンダリング）
  const onClickFunction = useCallback(() => {
    console.log((123456);
  }, []);

  return (
    <>
      {/* props の設定は通常通り */}
      <Sample onClickFunction={onClickFunction} />
      {/* ・・・ */}
    </>
  );
};
export default App;
```


# TBD

# Appendix

## 参考ページ

- [react.dev 公式サイト](https://react.dev/)
  - [react.dev クイックスタート](https://react.dev/learn)
  - [react.dev クイックスタート インストール](https://react.dev/learn/installation)
- [create-react-app.dev 公式サイト](https://create-react-app.dev/) 
- [nextjs.org 公式サイト](https://nextjs.org/)
- [tailwindcss.com 公式サイト create-react-app適用](https://tailwindcss.com/docs/guides/create-react-app)
- [Web簡易開発環境：codepen](https://codepen.io/)
- [Web簡易開発環境：codesandbox](https://codesandbox.io/)