Use Suspense or error boundary next to colocated query hook in same component #4201
-
I think it could be valuable to already include more error boundaries in our code instead of relying on
Thinking about this, I have yet to find a good solution for how to colocate a specific error boundary next to where you actually call the query. Here is a typical example on how one could use the function MyPage(): JSX.Element {
const { posts, isLoading, isError } = useQuery<Post[] | null>('posts', fetchPosts, { useErrorBoundary: false })
return (
<div>
<h1>Page header</h1>
<div>
<p>Posts:</p>
{isLoading ? (
<p>Loading..</p>
) : isError ? (
<p>Error while fetching posts</p>
) : (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
)}
</div>
</div>
)
} When one wants to use an error boundary instead, the natural thing to do is probably to wrap the data-related code with it: function MyPage(): JSX.Element {
- const { posts, isLoading, isError } = useQuery<Post[] | null>('posts', fetchPosts, { useErrorBoundary: false })
+ const { posts, isLoading } = useQuery<Post[] | null>('posts', fetchPosts, { useErrorBoundary: true })
return (
<div>
<h1>Page header</h1>
<div>
<p>Posts:</p>
+ <ErrorBoundary
+ fallbackRender={() => {
+ return <p>Error while fetching posts</p>
+ }}
+ >
{isLoading ? (
<p>Loading..</p>
- ) : isError ? (
- <p>Error</p>
) : (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
)}
+ </ErrorBoundary>
</div>
</div>
)
} This does obviously not work, because the error thrown by Alternative no. 1There is one way to restructure that, where everything related to fetching is put in a separate component, which can be wrapped by a boundary: function Data(): JSX.Element {
const { posts, isLoading } = useQuery<Post[] | null>('posts', fetchPosts, { useErrorBoundary: true })
return isLoading ? (
<p>Loading..</p>
) : (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
)
}
function MyPage(): JSX.Element {
return (
<div>
<h1>Page header</h1>
<div>
<p>Posts:</p>
<ErrorBoundary
fallbackRender={() => {
return <p>Error while fetching posts</p>
}}
>
<Data />
</ErrorBoundary>
</div>
</div>
)
} It feels a bit weird to describe an error "outside" and not next to whereever the data is used. Alternative no. 2Instead of an ad-hoc error fallback, one could rely on the I guess the same question will arise when we start using Suspense more, as it also has to be defined "outside". But the fallback value is most probably something more generic "loading" statement. You can see in the example for Suspense the described pattern (Alternative no. 1) is used, but I find it weird that the error for this query and the actual component that renders the query's data are separated - is having such wrapper components really the future canonical way for Suspense and error boundaries? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
yes. Your proposed solution doesn't work because |
Beta Was this translation helpful? Give feedback.
yes.
Your proposed solution doesn't work because
useQuery
is called outside of where theErrorBoundary
is rendered. This is kinda how error boundaries work in react - they throw it to the parent, so that's where the handling has to happen.