Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions src/content/reference/react/cache.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: cache

<RSC>

`cache` is only for use with [React Server Components](/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023#react-server-components).
`cache` is only for use with [React Server Components](/reference/rsc/server-components).

</RSC>

Expand Down Expand Up @@ -62,12 +62,10 @@ The optimization of caching return values based on inputs is known as [_memoizat

#### Caveats {/*caveats*/}

[//]: # 'TODO: add links to Server/Client Component reference once https://github.com/reactjs/react.dev/pull/6177 is merged'

- React will invalidate the cache for all memoized functions for each server request.
- Each call to `cache` creates a new function. This means that calling `cache` with the same function multiple times will return different memoized functions that do not share the same cache.
- `cachedFn` will also cache errors. If `fn` throws an error for certain arguments, it will be cached, and the same error is re-thrown when `cachedFn` is called with those same arguments.
- `cache` is for use in [Server Components](/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023#react-server-components) only.
- `cache` is for use in [Server Components](/reference/rsc/server-components) only.

---

Expand Down Expand Up @@ -103,6 +101,8 @@ Assume `Profile` is rendered first. It will call <CodeStep step={1}>`getUserMetr

When `TeamReport` renders its list of `users` and reaches the same `user` object, it will call <CodeStep step={2}>`getUserMetrics`</CodeStep> and read the result from cache.

If `calculateUserMetrics` can be aborted by passing an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal), you can use [`cacheSignal()`](/reference/react/cacheSignal) to cancel the expensive computation if React has finished rendering. `calculateUserMetrics` may already handle cancellation internally by using `cacheSignal` directly.

<Pitfall>

##### Calling different memoized functions will read from different caches. {/*pitfall-different-memoized-functions*/}
Expand Down Expand Up @@ -203,8 +203,6 @@ The <CodeStep step={1}>city</CodeStep> acts as a cache key.

<Note>

[//]: # 'TODO: add links to Server Components when merged.'

<CodeStep step={3}>Asynchronous rendering</CodeStep> is only supported for Server Components.

```js [[3, 1, "async"], [3, 2, "await"]]
Expand All @@ -213,8 +211,8 @@ async function AnimatedWeatherCard({city}) {
// ...
}
```
[//]: # 'TODO: add link and mention to use documentation when merged'
[//]: # 'To render components that use asynchronous data in Client Components, see `use` documentation.'

To render components that use asynchronous data in Client Components, see [`use()` documentation](/reference/react/use).

</Note>

Expand Down
121 changes: 121 additions & 0 deletions src/content/reference/react/cacheSignal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
---
title: cacheSignal
---

<Canary>

**The `cacheSignal()` API is currently only available in React’s Canary and Experimental channels.**

[Learn more about React’s release channels here.](/community/versioning-policy#all-release-channels)

</Canary>

<RSC>

`cacheSignal` is currently only used with [React Server Components](/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023#react-server-components).

</RSC>

<Intro>

`cacheSignal` allows you to know when the `cache()` life time is over.

```js
const signal = cacheSignal();
```

</Intro>

<InlineToc />

---

## Reference {/*reference*/}

### `cacheSignal` {/*cachesignal*/}

Call `cacheSignal` to get an `AbortSignal`.

```js {3,7}
import {cacheSignal} from 'react';
async function Component() {
await fetch(url, { signal: cacheSignal() });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example doesn't make sense because you have no idea that the fetch here is using cache().

Can you use something like a DB example, like here?

https://react-do5kq6ru7-fbopensource.vercel.app/reference/react/cache#preload-data

Copy link
Member Author

@eps1lon eps1lon Sep 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to know if the call is cached or not. Just that it may be cached by cache().

}
```

When React has finished rendering, the `AbortSignal` will be aborted. This allows you to cancel any in-flight work that is no longer needed.
Rendering is considered finished when:
- React has successfully completed rendering
- the render was aborted
- the render has failed

#### Parameters {/*parameters*/}

This function does not accept any parameters.

#### Returns {/*returns*/}

`cacheSignal` returns an `AbortSignal` if called during rendering. Otherwise `cacheSignal()` returns `null`.

#### Caveats {/*caveats*/}

- `cacheSignal` is currently for use in [React Server Components](/reference/rsc/server-components) only. In Client Components, it will always return `null`. In the future it will also be used for Client Component when a client cache refreshes or invalidates. You should not assume it'll always be null on the client.
- If called outside of rendering, `cacheSignal` will return `null` to make it clear that the current scope isn't cached forever.

---

## Usage {/*usage*/}

### Cancel in-flight requests {/*cancel-in-flight-requests*/}

Call <CodeStep step={1}>`cacheSignal`</CodeStep> to abort in-flight requests.

```js [[1, 4, "cacheSignal()"]]
import {cache, cacheSignal} from 'react';
const dedupedFetch = cache(fetch);
async function Component() {
await dedupedFetch(url, { signal: cacheSignal() });
}
```

<Pitfall>
You can't use `cacheSignal` to abort async work that was started outside of rendering e.g.

```js
import {cacheSignal} from 'react';
// 🚩 Pitfall: The request will not actually be aborted if the rendering of `Component` is finished.
const response = fetch(url, { signal: cacheSignal() });
async function Component() {
await response;
}
```
</Pitfall>

### Ignore errors after React has finished rendering {/*ignore-errors-after-react-has-finished-rendering*/}

If a function throws, it may be due to cancellation (e.g. <CodeStep step={1}>the Database connection</CodeStep> has been closed). You can use the <CodeStep step={2}>`aborted` property</CodeStep> to check if the error was due to cancellation or a real error. You may want to <CodeStep step={3}>ignore errors</CodeStep> that were due to cancellation.

```js [[1, 2, "./database"], [2, 8, "cacheSignal()?.aborted"], [3, 12, "return null"]]
import {cacheSignal} from "react";
import {queryDatabase, logError} from "./database";

async function getData(id) {
try {
return await queryDatabase(id);
} catch (x) {
if (!cacheSignal()?.aborted) {
// only log if it's a real error and not due to cancellation
logError(x);
}
return null;
}
}

async function Component({id}) {
const data = await getData(id);
if (data === null) {
return <div>No data available</div>;
}
return <div>{data.name}</div>;
}
```
9 changes: 7 additions & 2 deletions src/sidebarReference.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@
"title": "cache",
"path": "/reference/react/cache"
},
{
"title": "cacheSignal",
"path": "/reference/react/cacheSignal",
"version": "canary"
},
{
"title": "captureOwnerStack",
"path": "/reference/react/captureOwnerStack"
Expand Down Expand Up @@ -424,7 +429,7 @@
"path": "/reference/eslint-plugin-react-hooks/lints/incompatible-library",
"version": "rc"
},

{
"title": "preserve-manual-memoization",
"path": "/reference/eslint-plugin-react-hooks/lints/preserve-manual-memoization",
Expand All @@ -440,7 +445,7 @@
"path": "/reference/eslint-plugin-react-hooks/lints/refs",
"version": "rc"
},

{
"title": "set-state-in-effect",
"path": "/reference/eslint-plugin-react-hooks/lints/set-state-in-effect",
Expand Down