Biography ` doesn’t need to “wait” for the
` Albums ` to load.

The sequence will be:

  1. If ` Biography ` hasn’t loaded yet, ` BigSpinner ` is shown in place of the entire content area. 
  2. Once ` Biography ` finishes loading, ` BigSpinner ` is replaced by the content. 
  3. If ` Albums ` hasn’t loaded yet, ` AlbumsGlimmer ` is shown in place of ` Albums ` and its parent ` Panel ` . 
  4. Finally, once ` Albums ` finishes loading, it replaces ` AlbumsGlimmer ` . 

ArtistPage.js  Panel.js

ArtistPage.js

Reset  [ Fork
](https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-
react-app "Open in CodeSandbox")

    
    
    import { Suspense } from 'react';
    import Albums from './Albums.js';
    import Biography from './Biography.js';
    import Panel from './Panel.js';
    
    export default function ArtistPage({ artist }) {
      return (
        <>
          <h1>{artist.name}</h1>
          <Suspense fallback={<BigSpinner />}>
            <Biography artistId={artist.id} />
            <Suspense fallback={<AlbumsGlimmer />}>
              <Panel>
                <Albums artistId={artist.id} />
              </Panel>
            </Suspense>
          </Suspense>
        </>
      );
    }
    
    function BigSpinner() {
      return <h2>🌀 Loading...</h2>;
    }
    
    function AlbumsGlimmer() {
      return (
        <div className="glimmer-panel">
          <div className="glimmer-line" />
          <div className="glimmer-line" />
          <div className="glimmer-line" />
        </div>
      );
    }
    
    

Show more

Suspense boundaries let you coordinate which parts of your UI should always
“pop in” together at the same time, and which parts should progressively
reveal more content in a sequence of loading states. You can add, move, or
delete Suspense boundaries in any place in the tree without affecting the rest
of your app’s behavior.

Don’t put a Suspense boundary around every component. Suspense boundaries
should not be more granular than the loading sequence that you want the user
to experience. If you work with a designer, ask them where the loading states
should be placed—it’s likely that they’ve already included them in their
design wireframes.

* * *

###  Showing stale content while fresh content is loading

In this example, the ` SearchResults ` component suspends while fetching the
search results. Type ` "a" ` , wait for the results, and then edit it to `
"ab" ` . The results for ` "a" ` will get replaced by the loading fallback.

App.js

App.js

Reset  [ Fork
](https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-
react-app "Open in CodeSandbox")

    
    
    import { Suspense, useState } from 'react';
    import SearchResults from './SearchResults.js';
    
    export default function App() {
      const [query, setQuery] = useState('');
      return (
        <>
          <label>
            Search albums:
            <input value={query} onChange={e => setQuery(e.target.value)} />
          </label>
          <Suspense fallback={<h2>Loading...</h2>}>
            <SearchResults query={query} />
          </Suspense>
        </>
      );
    }
    
    

Show more

A common alternative UI pattern is to _defer_ updating the list and to keep
showing the previous results until the new results are ready. The [ `
useDeferredValue ` ](/reference/react/useDeferredValue) Hook lets you pass a
deferred version of the query down:

    
    
    export default function App() {  
    
    
      const [query, setQuery] = useState('');  
    
    
      const deferredQuery = useDeferredValue(query);  
    
    
      return (  
    
    
        <>  
    
    
          <label>  
    
    
            Search albums:  
    
    
            <input value={query} onChange={e => setQuery(e.target.value)} />  
    
    
          </label>  
    
    
          <Suspense fallback={<h2>Loading...</h2>}>  
    
    
            <SearchResults query={deferredQuery} />