feat(island): add Suspense component

This commit is contained in:
Julien Oculi 2024-07-01 14:19:42 +02:00
parent 1abc0d82c4
commit e0bc4c290f

50
islands/Suspens.tsx Normal file
View file

@ -0,0 +1,50 @@
// import { Suspense } from '@univoq // Error - mismatch in imports version
import { JSX } from 'preact'
import { useSignal } from '@preact/signals'
function RenderError(
{ error, fallback }: { error: Error; fallback: Fallback | undefined },
) {
if (fallback) {
return fallback({ error })
}
return (
<output>
<pre>{String(error)}</pre>
</output>
)
}
type Fallback = ({ error }: { error: Error }) => JSX.Element
export default function Suspense(
{ loader, fallback, signal, children }: {
loader: JSX.Element
children: Promise<JSX.Element>
fallback?: Fallback
signal?: AbortSignal
},
) {
const displayed = useSignal(loader)
signal?.addEventListener('abort', () => {
try {
signal.throwIfAborted()
} catch (error) {
displayed.value = RenderError({ error, fallback })
}
})
children
.then((element) => {
if (signal?.aborted) return
displayed.value = element
})
.catch((error) => {
if (signal?.aborted) return
displayed.value = RenderError({ error, fallback })
})
return <>{displayed}</>
}