ErrorBoundary
this component can handle any errors in children
props.fallback
If there is any thrown error in children of <ErrorBoundary/>
, Error will be caught and then fallback will be rendered.
import { ErrorBoundary } from '@suspensive/react'
import { useState, useEffect } from 'react'
const Example = () => (
<ErrorBoundary
fallback={(props) => (
<>
<button onClick={props.reset}>Try again</button>
{props.error.message}
</>
)}
>
<ErrorAfter4s />
</ErrorBoundary>
)
const ErrorAfter4s = () => {
const [asyncState, setAsyncState] = useState<{ isError: true; error: Error } | { isError: false; error: null }>({
isError: false,
error: null,
})
useEffect(() => {
setTimeout(() => {
setAsyncState({ isError: true, error: { status: 401, message: 'unauthorized' } })
}, 4000)
}, [])
if (asyncState.isError) {
throw asyncState.error
}
return <>No error</>
}
Define component as <ErrorBoundary/>
's fallback
ErrorBoundaryFallbackProps
If you want to deliver a declared component as <ErrorBoundary/>
's fallback, you can use the ErrorBoundaryFallbackProps
type to declare the component easily.
import type { ErrorBoundaryFallbackProps } from '@suspensive/react'
const ErrorBoundaryFallback = ({ reset, error }: ErrorBoundaryFallbackProps) => (
<>
<button onClick={reset}>reset</button>
{error.message}
</>
)
const Example = () => (
<ErrorBoundary fallback={ErrorBoundaryFallback}>
<ErrorAfter4s />
</ErrorBoundary>
)
Use <ErrorBoundary/>
fallback props without prop drilling
useErrorBoundaryFallbackProps
If component using reset
method and error
object is nested, prop drilling cannot be avoided.
The useErrorBoundaryFallbackProps
allows you to access the reset
method and error
objects without prop drilling.
import { ErrorBoundary, useErrorBoundaryFallbackProps } from '@suspensive/react'
const Nested = () => {
const { reset, error } = useErrorBoundaryFallbackProps()
return (
<>
<button onClick={reset}>Try again</button>
{error.message}
</>
)
}
// There's no need to pass fallback Prop here!
const ErrorBoundaryFallback = () => <Nested />
const Example = () => (
<ErrorBoundary fallback={ErrorBoundaryFallback}>
<Error />
</ErrorBoundary>
)
props.resetKeys
If you want to reset <ErrorBoundary/>
by component where is outside of <ErrorBoundary/>
's fallback. Inject any resetKey in resetKeys. resetKeys work only when at least one element of array is changed. you don't need to worry about provide new array as resetKeys like how useEffect's dependency array work.
import { ErrorBoundary } from '@suspensive/react'
import { useState } from 'react'
const Example = () => {
const [resetKey, setResetKey] = useState(0)
return (
<>
<button onClick={() => setResetKey((prev) => prev + 1)}>Try again</button>
<ErrorBoundary resetKeys={[resetKey]}>
<ErrorAfter4s />
</ErrorBoundary>
</>
)
}
props.onReset
This is a callback that is called first when <ErrorBoundary/>
reset. It can be used with @tanstack/react-query as follows.
import { ErrorBoundary } from '@suspensive/react'
import { QueryErrorResetBoundary } from '@tanstack/react-query'
const Example = () => (
<QueryErrorResetBoundary>
{({ reset }) => (
<ErrorBoundary
onReset={reset}
fallback={(props) => (
<>
<button onClick={props.reset}>Try again</button>
{props.error.message}
</>
)}
>
<Page />
</ErrorBoundary>
)}
</QueryErrorResetBoundary>
)
props.onError
This is a callback called when <ErrorBoundary/>
catches an error.
import { ErrorBoundary } from '@suspensive/react'
const logError = (error: Error, info: ErrorInfo) => {
// ...
}
const Example = (
<ErrorBoundary fallback={ErrorBoundaryFallback} onError={logError}>
<Error />
</ErrorBoundary>
)
useErrorBoundary
useErrorBoundary().setError
In children of <ErrorBoundary/>
, we can use useErrorBoundary().setError to make <ErrorBoundary/>
aware of the Error without throw.
import { ErrorBoundary, useErrorBoundary } from '@suspensive/react'
import { useEffect } from 'react'
const Example = () => (
<ErrorBoundary fallback={ErrorBoundaryFallback}>
<SetErrorAfterFetch />
</ErrorBoundary>
)
const SetErrorAfterFetch = () => {
const errorBoundary = useErrorBoundary()
useEffect(() => {
fetchSomething().then(
(response) => {},
(error) => errorBoundary.setError(error) // instead of throw inside
)
}, [])
return <>...</>
}
Controlling multiple <ErrorBoundary/>
s
<ErrorBoundary/>
is more powerful when used with <ErrorBoundaryGroup/>
. Control multiple <ErrorBoundary/>
s with <ErrorBoundaryGroup/>
.
Details are introduced in <ErrorBoundaryGroup/>
page.