React.cache を知らないと損する

# 結論
RSC で `React.cache` を知らないと損する

# 前提
:::message
Next.js の App Router を使用している前提
React.cache はサーバーコンポーネント専用のもの
:::

# なぜ？

`React.cache` を**使う場合**と**使わない場合**で比較したら一目瞭然

## 1. cache を使わない場合

`React.cache` を使わない場合のサンプルコードを以下に記す。

```tsx
// app/page.tsx
export default async function HelloAgain1() {
  const currentUser = await loadCurrentUser();
  return (
    <div>
      HelloAgain1 {currentUser.name}
      <HelloAgain2 />
    </div>
  );
}

async function HelloAgain2() {
  const currentUser = await loadCurrentUser();
  return <div>HelloAgain2 {currentUser.name}</div>;
}

const loadCurrentUser = async () => {
  console.log("loadCurrentUser");
  await new Promise((resolve) => setTimeout(resolve, 1000));
  return { id: "1", name: "Kimura" };
};
```

ページが読み込まれるまでの時間を
DevTools の NetWorkタブ で確認する。結果は??

![2.06秒](https://storage.googleapis.com/zenn-user-upload/570d3f45b51a-20250101.png)

**2.06秒！**
同じページ内で2回 `loadCurrentUser` が呼ばれているから当然！

## 2. cache を使う場合

`React.cache` を使う場合のサンプルコードを以下に記す。

```tsx
// app/page.tsx
import { cache } from "react";

export default async function HelloAgain1() {
  const currentUser = await loadCurrentUser();
  return (
    <div>
      HelloAgain1 {currentUser.name}
      <HelloAgain2 />
    </div>
  );
}

async function HelloAgain2() {
  const currentUser = await loadCurrentUser();
  return <div>HelloAgain2 {currentUser.name}</div>;
}

const loadCurrentUser = cache(async () => {
  console.log("loadCurrentUser");
  await new Promise((resolve) => setTimeout(resolve, 1000));
  return { id: "1", name: "Kimura" };
});
```

ページが読み込まれるまでの時間を
DevTools の NetWorkタブ で確認する。結果は??

![1.08秒](https://storage.googleapis.com/zenn-user-upload/57240771fb87-20250101.png)

**1.08秒！**

同じページ内で2回 `loadCurrentUser` がコード上では呼ばれているが、同じリクエストだから2回目のリクエストはキャッシュされていることが分かる

# 補足情報

[Next.js の Request Memoization](https://nextjs.org/docs/app/building-your-application/caching#request-memoization) の
セクションに以下の様に英語で記載されている

```
Good to know:

- Request memoization is a React feature, not a Next.js feature. It's included here to show how it interacts with the other caching mechanisms.
- Memoization only applies to the GET method in fetch requests.
- Memoization only applies to the React Component tree, this means:
  - It applies to fetch requests in generateMetadata, generateStaticParams, Layouts, Pages, and other Server Components.
  - It doesn't apply to fetch requests in Route Handlers as they are not a part of the React component tree.
- For cases where fetch is not suitable (e.g. some database clients, CMS clients, or GraphQL clients), you can use the React cache function to memoize functions.
```

⬇︎⬇︎⬇︎日本語に翻訳する⬇︎⬇︎⬇︎

```
知っておくとよいこと:

- リクエストのメモ化はReactの機能であり、Next.jsの機能ではありません。
- メモ化はフェッチリクエストのGETメソッドにのみ適用されます。
- メモ化はReactコンポーネントツリーにのみ適用されます。つまり
  - generateMetadata、generateStaticParams、Layouts、Pages、その他のServer Componentsのフェッチリクエストに適用されます。
  - ルートハンドラはReactコンポーネントツリーの一部ではないため、フェッチリクエストには適用されません。
- フェッチが適切でない場合（一部のデータベースクライアント、CMSクライアント、GraphQLクライアントなど）には、React.cache 関数を使用して関数をメモ化できます。
```

# 最後にもう一度結論

Request Memoization が
使用できる状況では `React.cache` を使おう！

特に GraphQL を使用しているプロジェクトや
fetch を使用していないプロジェクトでは必ず使おう！

# 参考文献

- [Request Memoization | Next.js公式](https://nextjs.org/docs/app/building-your-application/caching#request-memoization)
- [React's new cache function | YouTube](https://www.youtube.com/watch?v=MxjCLqdk4G4&t=304s)