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.
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 = useQuery(getDataSchema, []) useFallback(query, { data }) return query}// Let's assume fallback will always be available on the serverfunction 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 ...}