Skip to content

Commit

Permalink
Update post - Use Suspense + ErrorBoundary with data fetching
Browse files Browse the repository at this point in the history
  • Loading branch information
goplusgo committed Mar 21, 2022
1 parent b244040 commit f025b93
Showing 1 changed file with 40 additions and 29 deletions.
69 changes: 40 additions & 29 deletions _posts/2022-03-15-use-suspense--errorboundary-with-data-fetching.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,51 @@
---
layout: post
title: "Use Suspense + ErrorBoundary with data fetching"
title: 'Use Suspense + ErrorBoundary with data fetching'
tags: [React]
---

### What Is Suspense & ErrorBoundary, Exactly?
In short, `Suspense` is the boundary (or fallback) for data fetching in `loading` state while `ErrorBoundary` is the boundary (or fallback) for data fetching in `error` state.

### Traditional Data Fetch

Use [React-query](https://react-query.tanstack.com/examples/simple) as an example. Below is how we handle the data fetching regularly:

```javascript
function Example() {
const { isLoading, error, data, isFetching } = useQuery("repoData", () =>
axios.get(
"https://api.github.com/repos/tannerlinsley/react-query"
).then((res) => res.data)
const { isLoading, error, data, isFetching } = useQuery('repoData', () =>
axios
.get('https://api.github.com/repos/tannerlinsley/react-query')
.then((res) => res.data),
);

if (isLoading) return "Loading...";
if (isLoading) return 'Loading...';

if (error) return "An error has occurred: " + error.message;
if (error) return 'An error has occurred: ' + error.message;

return (
<div>
<h1>{data.name}</h1>
<p>{data.description}</p>
<strong>👀 {data.subscribers_count}</strong>{" "}
<strong>✨ {data.stargazers_count}</strong>{" "}
<strong>👀 {data.subscribers_count}</strong>{' '}
<strong>✨ {data.stargazers_count}</strong>{' '}
<strong>🍴 {data.forks_count}</strong>
<div>{isFetching ? "Updating..." : ""}</div>
<div>{isFetching ? 'Updating...' : ''}</div>
<ReactQueryDevtools initialIsOpen />
</div>
);
}
```

The drawback of this approach is:

1. We need to handle all different states (`loading`, `error` and `loaded`) of data fetching in a single react component;
2. It's difficult to propagate the data fetching states bottom-up;

### Data Fetch with Suspense + ErrorBoundary

#### 1. Enable suspense mode in React-query

```javascript
const queryClient = new QueryClient({
defaultOptions: {
Expand All @@ -54,9 +59,13 @@ const queryClient = new QueryClient({
#### 2. Wrap the react data fetching component with Suspense + ErrorBoundary

```javascript
import { ErrorBoundary } from "react-error-boundary";
import "bootstrap/dist/css/bootstrap.css";
import Spinner from "react-bootstrap/Spinner";
import { ErrorBoundary } from 'react-error-boundary';
import 'bootstrap/dist/css/bootstrap.css';
import Spinner from 'react-bootstrap/Spinner';

const GithubRepositoryName = React.lazy(() =>
import('./GithubRepositoryName.react'),
);

function ErrorFallback({ error, resetErrorBoundary }) {
return (
Expand All @@ -74,27 +83,29 @@ const spinner = (
</Spinner>
);

ReactDOM.render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<ErrorBoundary FallbackComponent={ErrorFallback}>
<Suspense fallback={spinner}>
<App />
</Suspense>
</ErrorBoundary>
</QueryClientProvider>
</React.StrictMode>,
document.getElementById("root")
);
const REPOSITORY = 'https://api.github.com/repos/goplusgo/react-flow-template';

export default function GithubProfile(): React.MixedElement {
return (
<ErrorBoundary FallbackComponent={ErrorFallback}>
<Suspense fallback={spinner}>
<GithubRepositoryName repository={REPOSITORY} />
</Suspense>
</ErrorBoundary>
);
}
```

where in `App.js`, we can then only focus on data successfully loaded rendering:
> Note: Use lazy import for GithubRepositoryName component.
where in `GithubRepositoryName.react.js`, we can then only focus on data successfully loaded rendering:

```javascript
export default function App(): React$MixedElement {
const { data } = useQuery("repoData", () =>
const { data } = useQuery('repoData', () =>
axios
.get("https://api.github.com/repos/goplusgo/react-flow-template")
.then((res) => res.data)
.get('https://api.github.com/repos/goplusgo/react-flow-template')
.then((res) => res.data),
);

return (
Expand Down

0 comments on commit f025b93

Please sign in to comment.