React Suspense
Using React Suspense with XSWR is super natural and easy
You just have to replace all your <Loader />
with suspend()
It will suspend until the next state change, where you will choose to throw an error, suspend again, or render your component
Note: Since useEffect doesn't work when suspended, suspend() will automatically run a deduped fetch(), to avoid waiting indefinitely
Example
A traditional React component...
function Component() {
const { data, error } = useData()
if (error) return <Error />
if (!data) return <Loader />
return <div>{JSON.stringify(data)}</div>
}
...now becomes
function Component() {
const { data, error, suspend } = useData()
// Throw the error
if (error) throw error
// Fetch and suspend until next state change
if (!data) throw suspend()
return <div>{JSON.stringify(data)}</div>
}
That's it, you have control over when you suspend and when you throw 🚀
Error handling
Throwing on error is entirely opt-in, you can also show a good old component
function Component() {
const { data, error, suspend } = useData()
// Show the error
if (error) return <>Error lol</>
// Fetch and suspend until next state change
if (!data) throw suspend()
return <div>{JSON.stringify(data)}</div>
}
If you decide to throw it, you can catch it with an Error Boundary (opens in a new tab).
Server-Side Rendering
Suspense doesn't work with SSR since the server can't use fetch. Or can it?
You can combine suspend()
with useFallback
function useData(data?: Data) {
const query = useSchema(getDataSchema, [])
useFallback(query, { data })
return query
}
// Let's assume fallback will always be available on the server
function Page(props: { data?: Data }) {
const { data, suspend } = useData(props.data)
if (error) throw error
// No data means we're on the client
if (!data) throw suspend()
return ...
}
Or use any custom logic to NOT suspend on the server
function Page() {
const ssr = useAreWeOnTheServer()
const { data, suspend } = useData()
if (error) throw error
if (!data && ssr) return <>Hi server</>
if (!data && !ssr) throw suspend()
return ...
}