React hook 一覧

- useState
    - useState()は、関数コンポーネントでstateを管理（stateの保持と更新）するためのReactフックであり、最も利用されるフックです。
        ```react:qiita.js
        const [state, setState] = useState()
        ```
- useEffect
  - 以下の流れで処理が走ります。
      1. useState の set 関数等によって関数の値が書き換える
      1. DOM を書き換える
      1. 画面を再レンダリングする
      1. レンダリング後に useEffect の第一引数に渡した処理を実行する
      ```react:qiita.js
      useEffect(() => {
      /* 第1引数には実行させたい副作用関数を記述*/
      console.log('副作用関数が実行されました！')
      },[依存する変数の配列]) // 第2引数には副作用関数の実行タイミングを制御する依存データを記述
      ```

- useLayoutEffect
    - useEffectは一度画面が描写された後にuseEffectの中の処理が実行されます。
        ```react:qiita.js
        // useEffectフックの場合は、一瞬ですが数字の（100）が表示された後に、0が表示されます。
        // これは一度、画面に描画された値がuseEffect内の処理が実行される動作となっております。
        import { useState, useEffect } from 'react';
    
        const App = () =>{
            const [count, setCount] = useState(100);
        
            useEffect(() => {
                setCount(0);
            }, []);
        
            return <div>{count}</div>;
        }
        ```
    - useLayoutEffectは画面が描写される前にuseLayoutEffectの中の処理が実行されます。
        ```react:qiita.js
        // useLayoutEffctフックでは画面が描写される前に実行されるので、初期値である（100）が画面に表示されることはなく0が表示されます。
        // useLayoutEffectフックが同期的に呼び出されるので、コンポーネントがマウントされる前に状態が更新されます。
        import { useState, useEffect } from 'react';
    
        const App = () =>{
            const [count, setCount] = useState(100);
        
            useLayoutEffect(() => {
                setCount(0);
            }, []);
        
            return <div>{count}</div>;
        }
        ```
        
- useContext
    - Reactコンポーネントのツリーに対して「グローバル」とみなすデータについて利用するように設計されています。
Contextによってコンポーネントツリー間におけるデータの橋渡しについて、すべての階層ごとに渡す必要性がなくなり、propsバケツリレーをしなくても下の階層で Contextに収容されているデータにアクセスできます。
      ```react:qiita.js
      import React, { useContext } from 'react';
      const MyContext = React.createContext();
      
      function MyComponent() {
          const value = useContext(MyContext);
          return <p>受け取ったデータ: {value}</p>;
      }
          
      function App() {
          return (
              <MyContext.Provider value="こんにちは、世界！">
                  <MyComponent />
              </MyContext.Provider>
          );
      }
      
      export default App;
      ```

- useMemo
    - 「値をメモ化」するフックス。依存配列の要素のいずれかが変化した場合のみ再計算を行う。
      ```react:qiita.js
      useMemo(() => 処理, [依存配列]);
      ```
    - 依存配列がある場合
      ```react:qiita.js
        // heightかweightが更新された時に再計算される
        const bmi = useMemo(() => calcBMI(height, weight), [height, weight]);
      ```
    - 依存配列がない場合
      ```react:qiita.js
        // 初回のみ実行され、2回目以降は実行されない
        const bmi = useMemo(() => calcBMI(height, weight), []);
      ```

- useCallback
    - 「コールバック関数をメモ化」するフックス。
useMemo同様、依存配列の要素のいずれかが変化した場合のみ再計算を行う。
    - コールバック関数とは
    - 関数の引数に渡す関数
        - 他の関数が実行された時に行う処理を登録するイメージ
        - 非同期処理が完了した時
        - ボタンをクリックした時など
      ```react:qiita.js
      useMemo(() => 処理, [依存配列]);
      ```
    - 依存配列がある場合
      ```react:qiita.js
        // heightかweightが更新された時に再計算される
        const bmi = useCallback(calcBMI(height, weight), [height, weight]);
      ```
    - 依存配列がない場合
      ```react:qiita.js
        // 初回のみ実行され、2回目以降は実行されない
        const bmi = useCallback(calcBMI(height, weight), []);
      ```

      - useRef
    - useRefはuseStateと似ていて、値を保持できますが、useRefの値が変更されても再レンダリングされない
    - 以下でボタンをクリックしてみると、変数 ref の値は増えていっていますが、"ref render"は画面が読み込まれたときのログのみとなっており、再レンダリングされていない
      ```react:qiita.js
        import { useRef } from "react";

        const Home = () => {
          let ref = useRef(0);
          console.log("ref render");

          const handleClick = () => {
            ref.current = ref.current + 1;
            console.log(ref.current);
          };

          return <button onClick={handleClick}>Click me!</button>;
        };

        export default Home;
      ```

    - DOM ノードへの参照を格納
    - 以下でdiv タグに ref 属性を付与
    - ボタンをクリックした際に、div タグの横幅を取得し、ログに出力しています。他にも DOM 要素にフォーカスを当てたり、スクロールしたり、サイズや位置を計測することができます。
      ```react:qiita.js
        import { useRef } from "react";

        const Home = () => {
          let divRef = useRef<HTMLDivElement>(null!);

        const handleClick = () => {
            const divWidth = divRef.current;
            console.log(divWidth.clientWidth);
        };

        return (
            <>
              <button onClick={handleClick}>click</button>
              <div className="bg-red-300" ref={divRef}>
                divタグ
              </div>
            </>
        );
        };

        export default Home;
      ```
      
  - useRecoilState
    - stateの取得・更新を行う場合、useRecoilState()を使用します。
    - stateの値を読み取るコンポーネントは、stateが更新されると自動的にレンダリングされます。

      ```react:qiita.js
        import { useRecoilState } from 'recoil'
        import { textState } from '../atoms/textState'

        export const TextInput = () => {
            // const [状態変数, 状態を変更するための関数] = useRecoilState(使用するstate)
            const [text, setText] = useRecoilState(textState)
  
            // 入力値でAtomを更新
            const handleChange = (e) => {
                setText(e.target.value)
            }

            return(
                <>
                  <input value="text" onChange={handleChange} />
                  <br />
                  出力: {text}
                </>
            )
        }
      ```

  - useRecoilValue
    - stateの値の取得のみを行う場合、useRecoilValue()を使用します(読み取り専用)。

      ```react:qiita.js
            import { useRecoilValue } from 'recoil'
            import { charCountState } from '../selectors/charCountState'

            export const CharacterCount.jsx = () => {
                // const 状態変数 = useRecoilValue(使用するstate)
                const count = useRecoilValue(charCountState)
  
                return <>文字数：　{count}</>
            }
      ```
        - useRouter
    - 現在のルート（ページ）に関する情報を取得したり、新しいルートにナビゲートしたりするための機能を提供
      ```react:qiita.js
      import { useRouter } from 'next/router'

      const MyComponent = () => {
      const router = useRouter()
    
      // 現在のルートに関する情報を取得できます。
      const pathname = router.pathname
      const query = router.query
      const asPath = router.asPath
    
      // 必要な処理を実行できます。
      if (pathname === '/home') {
        // ユーザーはホームページにいます。
      } else if (pathname === '/about') {
        // ユーザーはアバウトページにいます。
      }
    
      return (
        <div>
          <h1>My Component</h1>
          <p>現在のパスは {pathname}</p>
          <p>現在のクエリ文字列は {query}</p>
          <p>現在の asPath は {asPath}</p>
        </div>
      )
         }
 

- useReducer
    - useReducerは、ReactのHooks APIの1つです。新たなstateを返す関数を定義し、それをuseReducerの第一引数に渡すことで、stateを更新できます。
    - ```react:qiita.js
          function reducer (state, action) {
                  switch (action.type) {
                    case 'increment':
                      return { count: state.count + 1 }
                    case 'decrement':
                      return { count: state.count - 1 }
                    default:
                      throw new Error()
                  }
                }
                
                export default function App () {
                  const [state, dispatch] = useReducer(reducer, { count: 0 })
                
                  const increment = () => dispatch({ type: 'increment' })
                  const decrement = () => dispatch({ type: 'decrement' })
                
                  return (...)
                }
        ```
- useId
    - ユニークなIDとなる文字列を作成します
     ```react:qiita.js
        import { useId } from 'react';
        
        const id = useId()
        const id2 = useId()
        
        console.log(`id1 => ${id1}, id2 => ${id2}`)
        // id => :r1:, id2 => :r2:
    ```
```react:qiita.js
function PasswordField() {
    const passwordHintId = useId(); //引数は取らない
    return (
        <>
            <label>
                パスワード:
                <input
                    type="password"
                    aria-describedby={passwordHintId}
                />
            </label>
            <p id={passwordHintId}>
                パスワードは18桁以上で設定してください
            </p>
        </>
    );
}

function Form() {
    return (
        <>
            <p>パスワード設定</p>
            <PasswordField />
            <p>パスワード設定（確認用）</p>
            <PasswordField />
        </>
    )
}
```
- useTransition
    - useTransitionは、startTransitionという関数を提供していて、このstartTransitionに渡した関数内で状態を更新された場合、その状態更新でのレンダリングはノンブロッキングになる
    - 主な目的としては、レンダリングに非常に重い(遅い)処理がある画面レンダリングを遅延して、レンダリングが完了してから表示するために利用する
    - レンダリングに遅い処理がある場合、何も対応しないとその間画面操作がブロッキングされるのを防ぐ事ができる
     ```react:qiita.js
    function TabContainer() {
        const [isPending, startTransition] = useTransition();
        const [tab, setTab] = useState('about');

        function selectTab(nextTab) {
            startTransition(() => {
              setTab(nextTab);
            });
        }
    }
    ```
    - useTransitionは、2 つの値を配列として返す。
        - isPending: 現在レンダリングの遅延が発生しているか？
        - startTransition: 実際のトランジションをマークするための関数
    - startTransitionに渡された関数内で状態の更新が発生すると、その更新はトランジションとしてマークされ、画面表示はレンダリング完了まで遅延するようになる