useMemoとReact.memo と useCallback の違いと使い方

- **`useMemo`**: 計算結果をメモ化するために使用。重い計算を最適化。
- **`React.memo`**: コンポーネントのレンダリングを最適化。propsが変わらない限り再レンダリングを防ぐ。
- **`useCallback`**: 関数をメモ化するために使用。依存配列の変更がない限り、同じ関数参照を再利用。

### 1. `useMemo`

`useMemo`は、計算コストの高い値をメモ化するために使用されます。依存配列に指定した値が変更されない限り、前回の計算結果を再利用します。

```jsx
import React, { useMemo, useState } from 'react';

const ExpensiveComponent = ({ num }) => {
  const expensiveValue = useMemo(() => {
    console.log('計算中...');
    return num * 2; // 高コストな計算
  }, [num]);

  return <div>計算結果: {expensiveValue}</div>;
};

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

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>カウント: {count}</button>
      <ExpensiveComponent num={count} />
    </div>
  );
};
```

### 2. `React.memo`

`React.memo`は、コンポーネントのレンダリングを最適化するために使用されます。親コンポーネントが再レンダリングされても、propsが変更されない限り、子コンポーネントは再レンダリングされません。

```jsx
import React, { useState } from 'react';

const ChildComponent = React.memo(({ count }) => {
  console.log('ChildComponentがレンダリングされました');
  return <div>カウント: {count}</div>;
});

const App = () => {
  const [count, setCount] = useState(0);
  const [otherState, setOtherState] = useState(0);

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>カウント: {count}</button>
      <button onClick={() => setOtherState(otherState + 1)}>他の状態: {otherState}</button>
      <ChildComponent count={count} />
    </div>
  );
};
```

### 3. `useCallback`

`useCallback`は、関数をメモ化するために使用されます。依存配列に指定した値が変更されない限り、前回の関数を再利用します。これにより、子コンポーネントに渡す関数が毎回新しい参照を持つことを防ぎ、不要な再レンダリングを避けることができます。

```jsx
import React, { useCallback, useState } from 'react';

const Button = React.memo(({ onClick }) => {
  console.log('Buttonがレンダリングされました');
  return <button onClick={onClick}>クリック</button>;
});

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

  const handleClick = useCallback(() => {
    setCount(count + 1);
  }, [count]);

  return (
    <div>
      <Button onClick={handleClick} />
      <div>カウント: {count}</div>
    </div>
  );
};
```

### 4. `useMemo`と`useCallback`の似たような実装の例

例えば、数値を2倍にする関数をメモ化する場合、`useMemo`と`useCallback`の両方を使って実現することができます。

#### `useMemo`を使用した場合

```jsx
import React, { useMemo, useState } from 'react';

const App = () => {
  const [num, setNum] = useState(0);

  const doubledValue = useMemo(() => {
    console.log('計算中...');
    return num * 2; // 高コストな計算
  }, [num]);

  return (
    <div>
      <button onClick={() => setNum(num + 1)}>数を増やす: {num}</button>
      <div>2倍: {doubledValue}</div>
    </div>
  );
};
```

#### `useCallback`を使用した場合

```jsx
import React, { useCallback, useState } from 'react';

const App = () => {
  const [num, setNum] = useState(0);

  const double = useCallback(() => {
    console.log('計算中...');
    return num * 2; // 高コストな計算
  }, [num]);

  const doubledValue = double();

  return (
    <div>
      <button onClick={() => setNum(num + 1)}>数を増やす: {num}</button>
      <div>2倍: {doubledValue}</div>
    </div>
  );
};
```

### 違いのポイント

1. **目的**:
   - `useMemo`: 計算結果をメモ化して、再計算を避けるために使用します。
   - `useCallback`: 関数の参照をメモ化して、子コンポーネントの不必要な再レンダリングを防ぐために使用します。

2. **戻り値の性質**:
   - `useMemo`は、計算結果を返します。
   - `useCallback`は、関数自体を返します。

3. **使用シーン**:
   - `useMemo`は、重い計算や複雑なオブジェクトの生成などに使います。
   - `useCallback`は、特に子コンポーネントに関数を渡す場合に重要です。



| 特徴              | `useMemo`                                   | `useCallback`                               |
|-------------------|---------------------------------------------|---------------------------------------------|
| 目的              | 計算結果のメモ化                           | 関数のメモ化                                |
| 戻り値            | メモ化された値                              | メモ化された関数                            |
| 使用シーン        | 重い計算を行う場合に使用                   | 子コンポーネントに関数を渡す場合に使用    |
| 依存配列         | 依存する値が変更されると再計算             | 依存する値が変更されると新しい関数を生成 |