# react-suspense-boundary
**Repository Path**: mirrors_ecomfe/react-suspense-boundary
## Basic Information
- **Project Name**: react-suspense-boundary
- **Description**: A boundary component working with suspense and error
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-08-08
- **Last Updated**: 2026-04-25
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# react-suspense-boundary
A boundary component working with suspense and error
Version 2.x is implemented on [use-sync-external-store](https://www.npmjs.com/package/use-sync-external-store) to align with future official suspense data fetching.
## Install
```shell
npm install react-suspense-boundary
```
## Demo
See online demo here: [https://ecomfe.github.io/react-suspense-boundary/](https://ecomfe.github.io/react-suspense-boundary/)
You can start demo app yourself by executing:
```shell
npm start
```
## Usage
### Basic
```jsx
import {Boundary, CacheProvider, useResource} from 'react-suspense-boundary';
// Create or import an async function
const fetchInfo = ({id}) => fetch(`/info/${id}`).then(response => response.json());
// Implement your presentational component
function Info({id}) {
// Call `useResource` to fetch, note the return value is an array
const [info] = useResource(fetchInfo, {id});
// There is no `loading` branch, push returned object immediately to render
return (
{info.id}: {info.name}
);
};
// Data is stored inside `CacheProvider`, suspending state is controlled with `Boundary`
export default function App() => (
);
```
### CacheProvider
`CacheProvider` is by its name a cache context where we store all resources loaded by its children.
The simpliest way to use `CacheProvider` is to provider an application level top cache:
```tsx
import {render} from 'react-dom';
import {CacheProvider} from 'react-suspense-boundary';
import {App} from './components/App';
render(
,
document.getElementById('root')
);
```
For some more complex applications, you may want to restrict data caching in a smaller scope, e.g. route level, and expire cached responses on unmount, you can put `CacheProvider` anywhere you want to make a shared cache.
### Boundary
`Boundary` components defines a boundary in your view, within a boundary all async resource fetchings and errors are collected to form a loading or error indicator.
Usually we would have mulitple `Boundary` inside a `CacheProvider`, that is, users see different sections loading individually, but all resources are shared.
A `Boundary` component receives props below:
```typescript
interface RenderErrorOptions {
recover: () => void;
}
interface BoundaryProps {
// When any of async progress is pending, boundary will render this element
pendingFallback: ReactNode;
// When any error are received, will render this function
renderError(error: Error, options: RenderErrorOptions): ReactNode;
// When any error are catched, will call this function
onErrorCaught(error: Error, info: ErrorInfo): void;
}
```
### useResource
The `useResource` hook is used to inspect an async function within a boundary:
```ts
type Resource = [
T,
{
expire(): void;
refresh(): void;
}
];
function useResource(action: (input: I) => Promise, params: I): Resource;
function useConstantResource(action: () => Promise): Resource;
```
Unlike other async hooks, `useResource` returns the result "immediately", there is no `pending` or `loading` state, no exception will throw.
Other than the result itself, the second object of `useResource`'s returned array is a a bunch of functions to manually control the cache:
- `expire` will immediately remove the cached result, causing the upper `Boundary` to be pending until `action` is resolved the next time.
- `refresh` is a function to run `action` again without removing previously cached result.
### Default configuration
`BoundaryConfigProvider` provides default configurations to `pendingFallback`, `renderError` and `onErrorCaught` props.
```javascript
import {Spin} from 'antd';
import {BoundaryConfigProvider} from 'react-suspense-boundary';
const defaultPendingFallback = ;
const defaultRenderError = error => (
{error.message}
);
const App = () => {
{/* All Boundary elements inside it receives default configurations */}
}
```
### Preload
Preload is much like resource fetching, they can be "immediately" fired within a render function:
```ts
function usePreloadResource(action: (input: I) => Promise, params: I): void;
function usePreloadConstantResource(action: () => Promise): void;
```
Preload fires resource fetching process but not abort current render.
You can also get a `preload` function using `usePreloadCallback` hook to preload any resources in effect or event handlers:
```tsx
const preload = usePreloadCallback();
```
## Create Your Own Cache
`react-suspense-boundary`'s built-in `CacheProvider` references a single context type, that is, you are unable to access multiple caches in a single component:
```tsx
```
By default, there is no way to a make `MyResource` to load one resource into the outer `CacheProvider` and another into the inner `CacheProvider`.
To solve this issue, we provide a `create()` function to create a custom set of providers and hooks, with a different context type so that you can use them simultaneously:
```tsx
import {CacheProvider, create, useConstantResource} from 'react-suspense-boundary';
const {
CacheProvider: GlobalCacheProvider,
useConstantResource: useGlobalConstantResource,
} = create();
function MyResource() {
// Put current user resource into global cache
const [currentUser] = useGlobalConstantResource(fetchCurrentUser);
// And other resources into local one
const [dataSource] = useConstantResource(fetchList);
return (
// ...
);
}
```
`create` function also accepts an option object to customize context's display name:
```ts
interface CreateOptions {
cacheContextDisplayName?: string;
configContextDisplayName?: string;
}
```