diff --git a/src/content/reference/react/cache.md b/src/content/reference/react/cache.md
index 04836f19d24..7b6984736ee 100644
--- a/src/content/reference/react/cache.md
+++ b/src/content/reference/react/cache.md
@@ -4,7 +4,7 @@ title: cache
-`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).
@@ -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.
---
@@ -103,6 +101,8 @@ Assume `Profile` is rendered first. It will call `getUserMetr
When `TeamReport` renders its list of `users` and reaches the same `user` object, it will call `getUserMetrics` 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.
+
##### Calling different memoized functions will read from different caches. {/*pitfall-different-memoized-functions*/}
@@ -203,8 +203,6 @@ The city acts as a cache key.
-[//]: # 'TODO: add links to Server Components when merged.'
-
Asynchronous rendering is only supported for Server Components.
```js [[3, 1, "async"], [3, 2, "await"]]
@@ -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).
diff --git a/src/content/reference/react/cacheSignal.md b/src/content/reference/react/cacheSignal.md
new file mode 100644
index 00000000000..31b6a34a15b
--- /dev/null
+++ b/src/content/reference/react/cacheSignal.md
@@ -0,0 +1,121 @@
+---
+title: cacheSignal
+---
+
+
+
+**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)
+
+
+
+
+
+`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).
+
+
+
+
+
+`cacheSignal` allows you to know when the `cache()` life time is over.
+
+```js
+const signal = cacheSignal();
+```
+
+
+
+
+
+---
+
+## 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() });
+}
+```
+
+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 `cacheSignal` 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() });
+}
+```
+
+
+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;
+}
+```
+
+
+### 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. the Database connection has been closed). You can use the `aborted` property to check if the error was due to cancellation or a real error. You may want to ignore errors 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 No data available
;
+ }
+ return {data.name}
;
+}
+```
\ No newline at end of file
diff --git a/src/sidebarReference.json b/src/sidebarReference.json
index 8823effb2e1..fada659aa73 100644
--- a/src/sidebarReference.json
+++ b/src/sidebarReference.json
@@ -128,6 +128,11 @@
"title": "cache",
"path": "/reference/react/cache"
},
+ {
+ "title": "cacheSignal",
+ "path": "/reference/react/cacheSignal",
+ "version": "canary"
+ },
{
"title": "captureOwnerStack",
"path": "/reference/react/captureOwnerStack"
@@ -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",
@@ -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",