Skip to content

Commit 11fcb72

Browse files
committed
docs(Suspense): warn against module-level cache in SSR
Add a Pitfall on the Suspense reference page explaining that the hidden data.js cache must not be copied into server environments like Next.js, where module-level state can leak data across requests. Clarify the data.js comment in all Suspense examples accordingly. Fixes #8134
1 parent 8bb31ac commit 11fcb72

1 file changed

Lines changed: 22 additions & 0 deletions

File tree

src/content/reference/react/Suspense.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ React will display your <CodeStep step={1}>loading fallback</CodeStep> until all
5252

5353
In the example below, the `Albums` component *suspends* while fetching the list of albums. Until it's ready to render, React switches the closest Suspense boundary above to show the fallback--your `Loading` component. Then, when the data loads, React hides the `Loading` fallback and renders the `Albums` component with data.
5454

55+
<Pitfall>
56+
57+
Do not use a module-level cache like the one in `data.js` below in server environments such as Next.js. Module-level state persists across requests and can leak data between users. Use your framework's built-in caching, [`cache`](/reference/react/cache) in Server Components, or scope caches per request (for example, with a Context and `useRef`).
58+
59+
</Pitfall>
60+
5561
<Sandpack>
5662

5763
```js src/App.js hidden
@@ -121,6 +127,8 @@ export default function Albums({ artistId }) {
121127
// Note: the way you would do data fetching depends on
122128
// the framework that you use together with Suspense.
123129
// Normally, the caching logic would be inside a framework.
130+
// This module-level cache is only suitable for this client-only demo.
131+
// Do not copy it into server environments.
124132

125133
let cache = new Map();
126134

@@ -336,6 +344,8 @@ export default function Albums({ artistId }) {
336344
// Note: the way you would do data fetching depends on
337345
// the framework that you use together with Suspense.
338346
// Normally, the caching logic would be inside a framework.
347+
// This module-level cache is only suitable for this client-only demo.
348+
// Do not copy it into server environments.
339349

340350
let cache = new Map();
341351

@@ -598,6 +608,8 @@ export default function Albums({ artistId }) {
598608
// Note: the way you would do data fetching depends on
599609
// the framework that you use together with Suspense.
600610
// Normally, the caching logic would be inside a framework.
611+
// This module-level cache is only suitable for this client-only demo.
612+
// Do not copy it into server environments.
601613

602614
let cache = new Map();
603615

@@ -782,6 +794,8 @@ export default function SearchResults({ query }) {
782794
// Note: the way you would do data fetching depends on
783795
// the framework that you use together with Suspense.
784796
// Normally, the caching logic would be inside a framework.
797+
// This module-level cache is only suitable for this client-only demo.
798+
// Do not copy it into server environments.
785799

786800
let cache = new Map();
787801

@@ -966,6 +980,8 @@ export default function SearchResults({ query }) {
966980
// Note: the way you would do data fetching depends on
967981
// the framework that you use together with Suspense.
968982
// Normally, the caching logic would be inside a framework.
983+
// This module-level cache is only suitable for this client-only demo.
984+
// Do not copy it into server environments.
969985

970986
let cache = new Map();
971987

@@ -1225,6 +1241,8 @@ export default function Panel({ children }) {
12251241
// Note: the way you would do data fetching depends on
12261242
// the framework that you use together with Suspense.
12271243
// Normally, the caching logic would be inside a framework.
1244+
// This module-level cache is only suitable for this client-only demo.
1245+
// Do not copy it into server environments.
12281246

12291247
let cache = new Map();
12301248

@@ -1537,6 +1555,8 @@ export default function Panel({ children }) {
15371555
// Note: the way you would do data fetching depends on
15381556
// the framework that you use together with Suspense.
15391557
// Normally, the caching logic would be inside a framework.
1558+
// This module-level cache is only suitable for this client-only demo.
1559+
// Do not copy it into server environments.
15401560

15411561
let cache = new Map();
15421562

@@ -1848,6 +1868,8 @@ export default function Panel({ children }) {
18481868
// Note: the way you would do data fetching depends on
18491869
// the framework that you use together with Suspense.
18501870
// Normally, the caching logic would be inside a framework.
1871+
// This module-level cache is only suitable for this client-only demo.
1872+
// Do not copy it into server environments.
18511873

18521874
let cache = new Map();
18531875

0 commit comments

Comments
 (0)