@@ -229,6 +229,196 @@ Without a framework, you can read a Promise with `use` directly, as long as the
229229
230230</Note >
231231
232+ For example, both boundaries below are set up identically. The one on the left activates because its content reads a Promise with ` use ` , so it shows the ` fallback ` while loading. The one on the right fetches the same data inside an Effect, which Suspense can't detect, so its ` fallback ` never appears and the albums simply show up once the fetch resolves:
233+
234+ <Sandpack >
235+
236+ ``` js
237+ import { Suspense } from ' react' ;
238+ import Albums from ' ./Albums.js' ;
239+ import EffectAlbums from ' ./EffectAlbums.js' ;
240+
241+ export default function App () {
242+ return (
243+ < div className= " panels" >
244+ < section className= " panel" >
245+ < h2> Reads a Promise with use< / h2>
246+ < Suspense fallback= {< Loading / > }>
247+ < Albums artistId= " the-beatles" / >
248+ < / Suspense>
249+ < / section>
250+ < section className= " panel" >
251+ < h2> Fetches in an Effect< / h2>
252+ < Suspense fallback= {< Loading / > }>
253+ < EffectAlbums artistId= " the-beatles" / >
254+ < / Suspense>
255+ < / section>
256+ < / div>
257+ );
258+ }
259+
260+ function Loading () {
261+ return < p> 🌀 Loading... < / p> ;
262+ }
263+ ```
264+
265+ ``` js src/Albums.js active
266+ import { use } from ' react' ;
267+ import { fetchData } from ' ./data.js' ;
268+
269+ export default function Albums ({ artistId }) {
270+ // Reading the Promise with `use` activates
271+ // the Suspense boundary while it loads.
272+ const albums = use (fetchData (` /${ artistId} /albums` ));
273+ return (
274+ < ul>
275+ {albums .map (album => (
276+ < li key= {album .id }>
277+ {album .title } ({album .year })
278+ < / li>
279+ ))}
280+ < / ul>
281+ );
282+ }
283+ ```
284+
285+ ``` js src/EffectAlbums.js
286+ import { useState , useEffect } from ' react' ;
287+ import { fetchData } from ' ./data.js' ;
288+
289+ export default function EffectAlbums ({ artistId }) {
290+ const [albums , setAlbums ] = useState ([]);
291+
292+ useEffect (() => {
293+ let active = true ;
294+ fetchData (` /${ artistId} /albums` ).then (result => {
295+ if (active) {
296+ setAlbums (result);
297+ }
298+ });
299+ return () => {
300+ active = false ;
301+ };
302+ }, [artistId]);
303+
304+ // Suspense can't see this fetch, so its fallback never
305+ // shows. The list stays empty until the data arrives.
306+ return (
307+ < ul>
308+ {albums .map (album => (
309+ < li key= {album .id }>
310+ {album .title } ({album .year })
311+ < / li>
312+ ))}
313+ < / ul>
314+ );
315+ }
316+ ```
317+
318+ ``` js src/data.js hidden
319+ // Note: the way you would do data fetching depends on
320+ // the framework that you use together with Suspense.
321+ // Normally, the caching logic would be inside a framework.
322+
323+ let cache = new Map ();
324+
325+ export function fetchData (url ) {
326+ if (! cache .has (url)) {
327+ cache .set (url, getData (url));
328+ }
329+ return cache .get (url);
330+ }
331+
332+ async function getData (url ) {
333+ if (url === ' /the-beatles/albums' ) {
334+ return await getAlbums ();
335+ } else {
336+ throw Error (' Not implemented' );
337+ }
338+ }
339+
340+ async function getAlbums () {
341+ // Add a fake delay to make waiting noticeable.
342+ await new Promise (resolve => {
343+ setTimeout (resolve, 3000 );
344+ });
345+
346+ return [{
347+ id: 13 ,
348+ title: ' Let It Be' ,
349+ year: 1970
350+ }, {
351+ id: 12 ,
352+ title: ' Abbey Road' ,
353+ year: 1969
354+ }, {
355+ id: 11 ,
356+ title: ' Yellow Submarine' ,
357+ year: 1969
358+ }, {
359+ id: 10 ,
360+ title: ' The Beatles' ,
361+ year: 1968
362+ }, {
363+ id: 9 ,
364+ title: ' Magical Mystery Tour' ,
365+ year: 1967
366+ }, {
367+ id: 8 ,
368+ title: ' Sgt. Pepper\' s Lonely Hearts Club Band' ,
369+ year: 1967
370+ }, {
371+ id: 7 ,
372+ title: ' Revolver' ,
373+ year: 1966
374+ }, {
375+ id: 6 ,
376+ title: ' Rubber Soul' ,
377+ year: 1965
378+ }, {
379+ id: 5 ,
380+ title: ' Help!' ,
381+ year: 1965
382+ }, {
383+ id: 4 ,
384+ title: ' Beatles For Sale' ,
385+ year: 1964
386+ }, {
387+ id: 3 ,
388+ title: ' A Hard Day\' s Night' ,
389+ year: 1964
390+ }, {
391+ id: 2 ,
392+ title: ' With The Beatles' ,
393+ year: 1963
394+ }, {
395+ id: 1 ,
396+ title: ' Please Please Me' ,
397+ year: 1963
398+ }];
399+ }
400+ ```
401+
402+ ``` css
403+ .panels {
404+ display : flex ;
405+ gap : 20px ;
406+ }
407+
408+ .panel {
409+ flex : 1 ;
410+ padding : 0 15px ;
411+ border : 1px solid #eee ;
412+ border-radius : 8px ;
413+ }
414+
415+ .panel h2 {
416+ font-size : 1rem ;
417+ }
418+ ```
419+
420+ </Sandpack >
421+
232422---
233423
234424### Revealing content together at once {/* revealing-content-together-at-once* /}
0 commit comments