#Error Boundaries
Estimated reading time: 2 minutesError boundaries catch errors thrown by async components and render a fallback instead of crashing the entire tree.
#Usage
Import ErrorBoundary from @kitajs/html/error-boundary and wrap async components. The
catch prop accepts a JSX element or a function that receives the error.
async function function UserProfile({ id }: {
id: string;
}): Promise<string>
UserProfile ({ id: string id }: { id: string id : string }) {
const const user: {
name: string;
}
user = await let db: {
getUser(id: string): Promise<{
name: string;
}>;
}
db .function getUser(id: string): Promise<{
name: string;
}>
getUser (id: string id ) // may reject
return <JSX.IntrinsicElements.div: JSX.HtmlTag div JSX.HtmlTag.safe?: boolean | undefinedWhen set to true, all inner content (html or not) of this tag will be escaped
when evaluated.
Warning: This will escape even inner jsx tags. You should only use this in the
most inner tag of the html tree.
@example<div>{'<script />'}</div>
'<div><script /></div>'
<div safe>{'<script />'}</div>
'<div><script /></div>'
<div><div>{'<script />'}</div></div>
'<div><div><script /></div></div>'
// Escapes even inner jsx tags
<div safe><div>{'<script />'}</div></div>
'<div><div><script /></div></div>'
@defaultfalse@seehttps ://github.com/kitajs/html/tree/master/packages/html#sanitization safe >{const user: {
name: string;
}
user .name: string name }</JSX.IntrinsicElements.div: JSX.HtmlTag div >
}
const const html: string html = await (
<function ErrorBoundary(props: ErrorBoundaryProps): JSX.ElementA component that adds an error boundary to catch any inner promise rejection.
ErrorBoundary ErrorBoundaryProps.catch: JSX.Element | ((error: unknown) => JSX.Element)The error boundary to use if the async children throw an error.
The error will be string timeout if the rejection was caused by the timeout
property.
If the timeout gets triggered, it will throw an
{@linkcode
HtmlTimeout
}
error.
catch ={(err: unknown err ) => <JSX.IntrinsicElements.div: JSX.HtmlTag div JSX.HtmlTag.safe?: boolean | undefinedWhen set to true, all inner content (html or not) of this tag will be escaped
when evaluated.
Warning: This will escape even inner jsx tags. You should only use this in the
most inner tag of the html tree.
@example<div>{'<script />'}</div>
'<div><script /></div>'
<div safe>{'<script />'}</div>
'<div><script /></div>'
<div><div>{'<script />'}</div></div>
'<div><div><script /></div></div>'
// Escapes even inner jsx tags
<div safe><div>{'<script />'}</div></div>
'<div><div><script /></div></div>'
@defaultfalse@seehttps ://github.com/kitajs/html/tree/master/packages/html#sanitization safe >Error: {var String: StringConstructor
(value?: any) => string
Allows manipulation and formatting of text strings and determination and location of substrings within strings.
String (err: unknown err )}</JSX.IntrinsicElements.div: JSX.HtmlTag div >}>
<function UserProfile({ id }: {
id: string;
}): Promise<string>
UserProfile id: string id ="123" />
</function ErrorBoundary(props: ErrorBoundaryProps): JSX.ElementA component that adds an error boundary to catch any inner promise rejection.
ErrorBoundary >
)If UserProfile throws, the boundary renders the catch fallback. If it succeeds, the
boundary renders the component output unchanged.
#Sync components
Error boundaries only catch errors from async components, because synchronous errors propagate before the boundary can intercept them. For synchronous components, use a standard try/catch.
function function SyncComponent(): JSX.Element SyncComponent () {
try {
const const data: string data = function riskyOperation(): string riskyOperation ()
return <JSX.IntrinsicElements.div: JSX.HtmlTag div JSX.HtmlTag.safe?: boolean | undefinedWhen set to true, all inner content (html or not) of this tag will be escaped
when evaluated.
Warning: This will escape even inner jsx tags. You should only use this in the
most inner tag of the html tree.
@example<div>{'<script />'}</div>
'<div><script /></div>'
<div safe>{'<script />'}</div>
'<div><script /></div>'
<div><div>{'<script />'}</div></div>
'<div><div><script /></div></div>'
// Escapes even inner jsx tags
<div safe><div>{'<script />'}</div></div>
'<div><div><script /></div></div>'
@defaultfalse@seehttps ://github.com/kitajs/html/tree/master/packages/html#sanitization safe >{const data: string data }</JSX.IntrinsicElements.div: JSX.HtmlTag div >
} catch (function (local var) err: unknown err ) {
return <JSX.IntrinsicElements.div: JSX.HtmlTag div JSX.HtmlTag.safe?: boolean | undefinedWhen set to true, all inner content (html or not) of this tag will be escaped
when evaluated.
Warning: This will escape even inner jsx tags. You should only use this in the
most inner tag of the html tree.
@example<div>{'<script />'}</div>
'<div><script /></div>'
<div safe>{'<script />'}</div>
'<div><script /></div>'
<div><div>{'<script />'}</div></div>
'<div><div><script /></div></div>'
// Escapes even inner jsx tags
<div safe><div>{'<script />'}</div></div>
'<div><div><script /></div></div>'
@defaultfalse@seehttps ://github.com/kitajs/html/tree/master/packages/html#sanitization safe >Error: {var String: StringConstructor
(value?: any) => string
Allows manipulation and formatting of text strings and determination and location of substrings within strings.
String (function (local var) err: unknown err )}</JSX.IntrinsicElements.div: JSX.HtmlTag div >
}
}
<div>Loaded safely</div>#Combining with Suspense
Error boundaries and Suspense serve different purposes and are used together. Suspense's
catch prop handles errors from its async children. An ErrorBoundary wrapping the
Suspense handles errors from the fallback itself.
const const html: JSX.Element html = (
<function ErrorBoundary(props: ErrorBoundaryProps): JSX.ElementA component that adds an error boundary to catch any inner promise rejection.
ErrorBoundary ErrorBoundaryProps.catch: JSX.Element | ((error: unknown) => JSX.Element)The error boundary to use if the async children throw an error.
The error will be string timeout if the rejection was caused by the timeout
property.
If the timeout gets triggered, it will throw an
{@linkcode
HtmlTimeout
}
error.
catch ={<JSX.IntrinsicElements.div: JSX.HtmlTag div >Fallback failed</JSX.IntrinsicElements.div: JSX.HtmlTag div >}>
<function Suspense(props: SuspenseProps): JSX.ElementA component that returns a fallback while the async children are loading.
The rid prop is the one
{@linkcode
renderToStream
}
returns, this way the suspense
knows which request it belongs to.
Warning: Using Suspense without any type of runtime support will LEAK
memory and not work. Always use with renderToStream or within a framework that
supports it.
Suspense SuspenseProps.rid: string | numberThe request id is used to identify the request for this suspense.
rid ={const rid: "req-1" rid } SuspenseProps.fallback: JSX.ElementThe fallback to render while the async children are loading.
fallback ={<function AsyncFallback(): Promise<string> AsyncFallback />} SuspenseProps.catch?: JSX.Element | ((error: unknown) => JSX.Element) | undefinedThis error boundary is used to catch any error thrown by an async component and
streams its fallback instead.
Undefined behaviors happens on each browser kind when the html stream is unexpected closed by the server if an error is thrown. You should always define an error boundary to catch errors.
This does not catches for errors thrown by the suspense itself or async fallback
components. Please use
{@linkcode
ErrorBoundary
}
to catch them instead.
catch ={<JSX.IntrinsicElements.div: JSX.HtmlTag div >Children failed</JSX.IntrinsicElements.div: JSX.HtmlTag div >}>
<function AsyncContent(): Promise<string> AsyncContent />
</function Suspense(props: SuspenseProps): JSX.ElementA component that returns a fallback while the async children are loading.
The rid prop is the one
{@linkcode
renderToStream
}
returns, this way the suspense
knows which request it belongs to.
Warning: Using Suspense without any type of runtime support will LEAK
memory and not work. Always use with renderToStream or within a framework that
supports it.
Suspense >
</function ErrorBoundary(props: ErrorBoundaryProps): JSX.ElementA component that adds an error boundary to catch any inner promise rejection.
ErrorBoundary >
)If AsyncContent throws, Suspense renders "Children failed". If AsyncFallback throws,
the ErrorBoundary renders "Fallback failed". These are independent error paths.