React Suspense
Learn how the Sanity App SDK uses established React patterns to facilitate working with live content.
The App SDK hooks are optimized for use with React Suspense. This allows you to write code in a synchronous fashion, as if the data you’re requesting from our hooks is available immediately.
For example, note in the example below how we use the value returned by the useProjects
hook without checking if the request for it is in flight or resolved:
// ProjectsList.tsx
import {useProjects} from '@sanity/sdk-react'
import ProjectListItem from './ProjectListItem'
export function ProjectsList() {
const projects = useProjects()
return (
<ul>
{projects.map((project) => (
<li key={project.id}>
<ProjectListItem projectId={project.id} />
</li>
))}
</ul>
)
}
Rendering fallback content
Because our hooks suspend during data fetching, you can render fallback content until data fetching is resolved using Suspense boundaries.
For example, given the above Projects List component (which uses the useProjects
hook), we can wrap instances of this component with a Suspense boundary as follows:
// ProjectsPanel.tsx
import {Suspense} from 'react'
import ProjectsList from './ProjectsList'
import LoadingSkeleton from './LoadingSkeleton'
export function ProjectsPanel() {
return (
<Suspense fallback={<LoadingSkeleton />}>
<ProjectsList />
</Suspense>
)
}
Additionally, if the ProjectListItem
component made use of the useProject
hook, we could also wrap its component instances in Suspense boundaries within the ProjectsList
component:
// ProjectsList.tsx
import Suspense from 'react'
import {useProjects} from '@sanity/sdk-react'
import ProjectListItem from './ProjectListItem'
export function ProjectsList() {
const projects = useProjects()
return (
<ul>
{projects.map((project) => (
<li key={project.id}>
<Suspense fallback={'Loading project…'}>
<ProjectListItem projectId={project.id} />
</Suspense>
</li>
))}
</ul>
)
}
Notes
- The
SanityApp
component rendered by all Sanity custom apps comes with a root level Suspense boundary baked in. You can (and should!) pass a fallback component to itsfallback
prop to use as fallback content at the root level of your app. You may wish to wrap other components which use our hooks in a Suspense boundary. To learn more about how Suspense works, refer to the React Suspense docs. - Our hooks also make use of
useTransition
internally in order to keep UI that has already been rendered responsive and visible during data fetching.
Was this page helpful?