Skip to content

Commit fad7999

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 6be2b02 commit fad7999

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
@@ -79,6 +79,12 @@ React will display your <CodeStep step={1}>loading fallback</CodeStep> until all
7979

8080
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.
8181

82+
<Pitfall>
83+
84+
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`).
85+
86+
</Pitfall>
87+
8288
<Sandpack>
8389

8490
```js src/App.js hidden
@@ -148,6 +154,8 @@ export default function Albums({ artistId }) {
148154
// Note: the way you would do data fetching depends on
149155
// the framework that you use together with Suspense.
150156
// Normally, the caching logic would be inside a framework.
157+
// This module-level cache is only suitable for this client-only demo.
158+
// Do not copy it into server environments.
151159

152160
let cache = new Map();
153161

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

602612
let cache = new Map();
603613

@@ -860,6 +870,8 @@ export default function Albums({ artistId }) {
860870
// Note: the way you would do data fetching depends on
861871
// the framework that you use together with Suspense.
862872
// Normally, the caching logic would be inside a framework.
873+
// This module-level cache is only suitable for this client-only demo.
874+
// Do not copy it into server environments.
863875

864876
let cache = new Map();
865877

@@ -1044,6 +1056,8 @@ export default function SearchResults({ query }) {
10441056
// Note: the way you would do data fetching depends on
10451057
// the framework that you use together with Suspense.
10461058
// Normally, the caching logic would be inside a framework.
1059+
// This module-level cache is only suitable for this client-only demo.
1060+
// Do not copy it into server environments.
10471061

10481062
let cache = new Map();
10491063

@@ -1228,6 +1242,8 @@ export default function SearchResults({ query }) {
12281242
// Note: the way you would do data fetching depends on
12291243
// the framework that you use together with Suspense.
12301244
// Normally, the caching logic would be inside a framework.
1245+
// This module-level cache is only suitable for this client-only demo.
1246+
// Do not copy it into server environments.
12311247

12321248
let cache = new Map();
12331249

@@ -1487,6 +1503,8 @@ export default function Panel({ children }) {
14871503
// Note: the way you would do data fetching depends on
14881504
// the framework that you use together with Suspense.
14891505
// Normally, the caching logic would be inside a framework.
1506+
// This module-level cache is only suitable for this client-only demo.
1507+
// Do not copy it into server environments.
14901508

14911509
let cache = new Map();
14921510

@@ -1799,6 +1817,8 @@ export default function Panel({ children }) {
17991817
// Note: the way you would do data fetching depends on
18001818
// the framework that you use together with Suspense.
18011819
// Normally, the caching logic would be inside a framework.
1820+
// This module-level cache is only suitable for this client-only demo.
1821+
// Do not copy it into server environments.
18021822

18031823
let cache = new Map();
18041824

@@ -2110,6 +2130,8 @@ export default function Panel({ children }) {
21102130
// Note: the way you would do data fetching depends on
21112131
// the framework that you use together with Suspense.
21122132
// Normally, the caching logic would be inside a framework.
2133+
// This module-level cache is only suitable for this client-only demo.
2134+
// Do not copy it into server environments.
21132135

21142136
let cache = new Map();
21152137

0 commit comments

Comments
 (0)