Reactメモ

# Reactとは
:::note
Metaが開発した`JavaScript`のライブラリ
:::

以下の3つの特徴がある。
* Declarative(宣言的)
* Component-Base(コンポーネントベース)
* Learn Once, Write Anywhere(一度の学びでなんでも書ける)


# JSXとは
:::note
`JavaScript`でHTML文を書けるように拡張したもののこと。
:::
`JavaScript`の拡張構文が`JSX`なのに対して、`TypeScript`でHTML文を書けるように拡張したものが`TSX`。
`TSX`内で`JavaScript`の構文を適応したい場合は`{}`で囲うことで使うことができる。

# コンポーネントとは
:::note
見た目と振る舞いをセットにしたUI部品の最小単位のこと。
:::
Reactには関数コンポーネントとクラスコンポーネントがあったが`Hooks`の登場で関数コンポーネントを使うのが一般的になった。




# Contextとは


# React Hooks
ルール
Hookを呼び出すのはReactの関数内のみ。
## useState
`useState`はコンポーネントの状態を管理するためのHook。
```typescript
const [状態を表す変数,状態を変化させる関数名] = useState(状態の初期値)
```
```typescript:使用例
const [count, setCount] = useState(0)
// countの値を更新
setCount(count+1)
// またはこっち
setCount((preCount)=>preCount+1)
```
:::note
状態を変化させる関数の名前は`set変数名`とすることが通例。
:::

`useState`でオブジェクトや配列を扱う場合はスプレッド構文（`{...}`）を用いて展開し、変更点を追加で記述する必要がある。
`useState`の場合、更新関数に渡された値は**既存の状態にマージするのではなく、新たな状態として置換してしまう**ため、元のオブジェクトや配列を展開して前回の状態を残す必要がある。

```js:オブジェクトの場合
const [obj, setObj] = useState({})
// 値の更新
setObj({...obj,追加する値})
```

```js:配列の場合
const [arr, setArr] = useState([])
// 値の更新
setArr([...arr,追加する値])
```

## useReducer
`useState`と同様にコンポーネントの状態を管理するHook。
`useState`は`useReducer`に内部実装されている。
```js:使用例
const [state, dispatch] = useReducer(reducer,初期値)
```
`state`は状態を表す変数で、`state`の更新関数が`reducer`。
`dispatch`は`reducer`を呼び出す関数のこと。

```js:呼び出し例
dispatch(action)
```
`reducer`の呼び出しには`dispatch`にオブジェクト`actoin`を引数に渡すことで、更新関数の`reducer`が発火。

```js:reducerの関数定義
const reducer = (state, action) => {
    // actionに応じた処理内容
    return 次のstateの値
}
```
`reducer`に引き渡される引数はコンポーネントの状態を示す`state`、`dispatch`から渡されるオブジェクト`action`がある。
`action`内の指定のプロパティに対しての処理を`switch`文などで書いていく。

## useStateとuseReducerの使い分け
`useState`と`useReducer`は状態を更新するという意味では役割が似ている。以下のような条件で使い分けると可読性の面でも優れる。
|項目|useState|useReducer|
|:-:|:-:|:-:|
|扱うステートの型|Number, String, Boolean|Object, Array|
|関連するステートを扱う|×|◯|
|ローカルorグローバル|ローカル|グローバル<br>useContext()と併用する|



## useEffect
DOMの更新後に呼び出したい処理を指定することができるHook。
```js
useEffect(()={
              //処理内容
              },[状態変化を監視するステート名])
```
:::note
**DOM更新後**に実行されるため`useEffect`が呼び出されたときは適切にDOMの更新が行われたことを示す。
:::
※初回`render`時と、指定したステートがあれば、そのステートが更新されるごとに実行される。

```js:使用例
// ステートの設定
const [count, setCount] = useState(0)
const [value, setValue] = useState('')

// ページタイトルを変更
useEffect(()={
              document.title = `{count}`
              })
```
この場合、ステートを指定していないため`useEffect`は以下の状況で実行される。
* 初回`render`時
* `count`が更新された時
* `value`が更新された時

処理内容的には`count`が更新された時だけ`useEffect`が発火すれば問題ないので、ステートを指定して、発火回数を減らすことができる。

```js:使用例（ステートを指定した場合）
const [count, setCount] = useState(0)
const [value, setValue] = useState('')

// ページタイトルを変更
useEffect(()={
              document.title = `{count}`
              },[count])
```
`useEffect`の第二引数の配列の中に監視したいステートを指定することでそのステートが更新された時のみ発火し、それ以外は無視するということができる。
この場合、`useEffect`は以下の状況で実行される。
* 初回`render`時
* `count`が更新された時

このようにすることで、`value`が更新された場合、発火を無視することができる。

また第二引数に空の配列（`[]`）を指定した場合は処理を初回`render`時のみ実行されるようにすることができる。

```js:初回のみ実行
const [count, setCount] = useState(0)
const [value, setValue] = useState('')

// ページタイトルを変更
useEffect(()={
              document.title = `{count}`
              },[])
```
この場合初回`render`時のみ発火されるので、ページタイトルは`0`のままとなる。

また`useEffect`で指定した関数に`return`を設定することで、そのコンポーネントがDOMから削除（アンマウント）された時に実行する処理を指定することができる。

```js:アンマウント時の処理
useEffect(()={
              // マウスが動いた時の処理を追加
              window.addEventListener('mousemove',実行される関数)
              return () => {
                // アンマウント時に実行される処理
                // 登録した処理を削除
                window.removeEventListener('mousemove',実行される関数)
              }

})
```

わかりやすい記事

https://qiita.com/cheez921/items/f3ff76865f943345107c

## useContext
コンポーネントのデータを親コンポーネントから橋渡ししなくても扱えるようにするHook。

書き方は以下の通り。
```js:渡す側
import {createContext} from 'react'
import {ComponentC} from './component/ComponentC'

export const UserContext = createContext()

export function App() {
  const [user, setUser] = useState({name:'yamada',age:32})
  return (
    <div className="App">
      <UserContext.Provider value={user}>
        <ComponentC />
      </UserContext.Provider>
    </div>
  );
}
```
渡したいコンポーネントを作成したContextのProviderである`UserContext.Provider`で囲む。
この時`value`に引き渡したい変数を渡す。
この時作成した`Context`は他のファイルで用いるため`export`している。

```js:受け取る側
import React, { useContext } from 'react'
import {UserContext} from '../App'

export function ComponentF(){
  const user = useContext(UserContext)
   return (
     <div>
      {user.name}
      </div>
   )  
}
```
※`ComponentF`は`ComponentC`に内包されているとする。

`useContext`を用いて、渡された`Context`を受け取り、変数に入れることができる。
以降はそのスコープ内で変数を用いて値を使用することができる。

## useRef
要素への参照を行うHook。

:::note
`useState`のように値の保持を行うことができるが、`useState`とは違い値が更新されても再レンダーされないのが特徴。
:::

```js:使用例
const ref = useRef(初期値)
```
`useRef`はコンポーネントのトップレベルで呼び出して変数を宣言する必要がある。
宣言時`current`プロパティに初期値が入っているオブジェクトを返す。
主に**値を参照する場合**、**DOM操作を行う場合**に用いられる。

### 値を参照する場合
参照したい値を`useRef`で定義し、更新には`current`プロパティを指定して再代入することでレンダリングはそのままで値の更新が行うことができる。
```js
// 参照したい値の定義
const count = useRef(0)

// 値の更新
count.current  = 1
```


### DOM操作を行う場合
操作したいDOMノードのJSXに定義した`refオブジェクト`を引き渡す。
引き渡されたDOMは`current`に格納されるので、`current`プロパティを指定して、通常のDOM操作を行う。
```js
// useRefの定義
const inputDom = useRef(null)

// DOMの指定（JSX内）
return <input ref={inputDom} />

// DOMの操作（入力欄にフォーカスする）
inputDom.current.focus()
```



# パフォーマンス向上に役立つHook

## useCallback

## useMemo