React hooksを理解する（useCallback）

## 目次

##### 1.useCallbackとは？
##### 2.useCallbackの基本的な使い方
##### 3.useCallbackを使うメリット
##### 4.useCallbackの実践例
##### 5.useCallbackの注意点
##### 6.useCallbackとuseMemoの違い
##### 7.useCallbackとReact.memoの違い
##### 8.まとめ

## useCallbackとは？

`useCallback`は、Reactでメモ化したコールバック関数を作成するためのフック です。

通常、React ではコンポーネントが再レンダリングされるたびに関数が再生成されるという仕様があります。これは問題になることは少ないですが、以下のような場合に不要なレンダリングや処理の無駄を防ぐために`useCallback`が役立ちます。

#### useCallback が必要なケース
- 関数をメモ化して、無駄な再生成を防ぐ
- 子コンポーネントに渡す関数が再生成されることを防ぎ、不要な再レンダリングを抑える
- パフォーマンスを最適化するための最適化（React.memo と組み合わせる）

## useCallback の基本的な使い方

#### インポート方法

`useCallback`はReactのフックなので、reactからインポートします。

```jsx

import React, { useCallback } from 'react';

```

#### 基本構文

```jsx

const memoizedFunction = useCallBack(() => {
    // 関数の処理
}, [依存する値]);

```

#### :pencil2: 解説

- `useCallback`は第1引数に関数を取り、第2引数に依存配列を指定します。
- 依存配列の値が変わらない限り、関数は再生成されません。

#### シンプルな例

通常の関数では、コンポーネントが再レンダリングされるたびに関数が新しく作成されます。


```jsx

function Example() {
  const handleClick = () => {
    console.log("ボタンがクリックされました");
  };

  return <button onClick={handleClick}>クリック</button>;
}

```

しかし、useCallback を使うと 関数のメモ化（再利用） が可能になります。

```jsx

import React, { useCallback } from "react";

function Example() {
  const handleClick = useCallback(() => {
    console.log("ボタンがクリックされました");
  }, []);

  return <button onClick={handleClick}>クリック</button>;
}

```

#### :pencil2: 解説

- handleClickは最初のレンダリング時に一度だけ作成され、それ以降は再利用される。
- 依存配列 [] を空にすると、コンポーネントが再レンダリングされても関数は再生成されない。


## useCallbackを使うメリット

#### 1.子コンポーネントの不要な再レンダリングを防ぐ
- useCallback を使わない場合、親コンポーネントが再レンダリングされると、子コンポーネントに渡す関数も毎回新しく作られてしまい、子コンポーネントが無駄に再レンダリングされる 可能性があります。
##### 2. パフォーマンスの最適化
- 再生成を避けることで、処理のオーバーヘッドを削減 できる。
- 特にReact.memoと組み合わせると、最適化の効果が高まる。

## useCallbackの実践例

##### 子コンポーネントの再レンダリングを抑える

`useCallback`を使わないと、親コンポーネントが再レンダリングされるたびに子コンポーネントに渡す関数が新しくなり、子コンポーネントが不要に再レンダリングされてしまいます。

```jsx

import React, { useState } from 'react';

function child({ handleClick }) {
    console.log("Child コンポーネントがレンダリングされました。");
    return <button onClick={handleClick}>クリック</button>;
}

function Parent() {
    const [count, setCount] = useState(0);

    // 毎回新しい関数が作られる
    const handleClick = () => {
        console.log("ボタンがクリックされました。");
    };

    return (
        <div>
            <p>カウント: {count}</p>
            <button onClick={() => setCount(count +1)}>カウントアップ</button>
            <Child handelClick={handleClick} />
        </div>
    );
}

export default Parent;

```

#### :pencil2: 解説

- `Parent`が再レンダリングされるたびに`handleClick`が再生成され、`Child`が不要にレンダリングされる。

#### 解決策（`useCallback`を使用）

```jsx

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

function Child({ handleClick }) {
  console.log("Child コンポーネントがレンダリングされました");
  return <button onClick={handleClick}>クリック</button>;
}

const MemoizedChild = React.memo(Child);

function Parent() {
  const [count, setCount] = useState(0);

  // useCallback を使用して関数をメモ化
  const handleClick = useCallback(() => {
    console.log("ボタンがクリックされました");
  }, []);

  return (
    <div>
      <p>カウント: {count}</p>
      <button onClick={() => setCount(count + 1)}>カウントアップ</button>
      <MemoizedChild handleClick={handleClick} />
    </div>
  );
}

export default Parent;


```

#### :pencil2: 解説

- `handleClick`がメモ化され、`Parent`が再レンダリングされても`Child`が無駄に再レンダリングされない！
- `React.memo`を使うことで`Child`の再レンダリングを防止。

 #### useCallback の注意点

#### 1.むやみに使うと逆効果
- 使いすぎるとメモリを消費するため、最適化どころかパフォーマンスが悪化する可能性がある。
- 必要な場面だけに適用する（子コンポーネントの React.memo との組み合わせが有効）。

#### 2.依存配列を適切に設定する
- 依存配列が適切でないと、古い状態を参照してしまい、意図しない動作をすることがある。

## `useCallback`と`useMemo`の違い

| | `useCallback` | `useMemo` |
|:-|:-|:-|
|  **目的** |  関数をメモ化する |  計算結果をメモ化する |
|  **戻り値** |  メモ化された関数 |  	メモ化された値 |
| **使いどころ**  | コールバック関数の再生成を防ぐ  | 計算コストの高い値をキャッシュする  |
| **例** | `const memoizedFn = useCallback(() => {}, [deps]);` | `const memoizedValue = useMemo(() => computeValue(), [deps]);` | 

## `useCallback`と`React.memo`の違い

| | `useCallback` | `React.memo` |
|:-|:-|:-|
|  **目的** |  関数をメモ化する |  コンポーネントをメモ化する |
|  **戻り値** |  メモ化された関数 |  	メモ化されたコンポーネント |
| **使いどころ**  | コールバック関数の再生成を防ぐ  | コンポーネントの再レンダリングを抑え、不要な描画を防ぐ  |
| **例** | `const memoizedFn = useCallback(() => {}, [deps]);` | `const MemoizedComponent = React.memo(Component);` | 

## まとめ

- `useCallback`は関数をメモ化し、再レンダリング時の無駄な関数再生成を防ぐ。
- 子コンポーネントの再レンダリングを抑える のに役立つ。
- `React.memo`と組み合わせると効果的。
- 適切な場面で使わないと逆効果になることもある。
- `useMemo` は値のメモ化、`useCallback`は関数のメモ化をする点が違う。