跳到主要内容

<AsyncBoundary />

处理 Suspense 的加载与错误状态。

在 React 18 中,它会创建一个并发拆分;在 16 和 17 中,它会显示加载 fallback。如果出现无法恢复的错误,它会显示错误 fallback。

提示

通过学习如何就近声明数据依赖,进一步了解边界应该放在哪里

用法​

将 AsyncBoundary 放在页面、路由或模态框等导航边界处或其上方。

Dashboard.tsx
import { AsyncBoundary } from '@data-client/react';
import { Outlet } from 'react-router';

export default function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
<section>
<AsyncBoundary>
<Outlet />
</AsyncBoundary>
</section>
</div>
);
}

然后在渲染数据的组件中使用 useSuspense()。<AsyncBoundary /> 的任何后代产生的错误或加载状态都会在 <AsyncBoundary /> 处渲染。这种对 fallback UI 的整合可以提升性能和可用性。

function SuspendingComponent() {
const data = useSuspense(getMyThing);

return <div>{data.text}</div>;
}

Props​

interface BoundaryProps {
children: React.ReactNode;
fallback?: React.ReactNode;
errorClassName?: string;
errorComponent?: React.ComponentType<{
error: NetworkError;
resetErrorBoundary: () => void;
className?: string;
}>;
listen?: (resetListener: () => void) => () => void;
}

fallback​

加载时显示的任意可渲染(React Node)元素

errorComponent​

用于处理捕获到的错误的组件

自定义 fallback 示例​

import React from 'react';
import { DataProvider, AsyncBoundary } from '@data-client/react';
import Router from './Router';

function ErrorPage({
error,
className,
resetErrorBoundary,
}: {
error: Error;
resetErrorBoundary: () => void;
className?: string;
}) {
return (
<pre role="alert" className={className}>
{error.message} <button onClick={resetErrorBoundary}>Reset</button>
</pre>
);
}

export default function App() {
return (
<DataProvider>
<AsyncBoundary fallback="loading" errorComponent={ErrorPage}>
<Router />
</AsyncBoundary>
</DataProvider>
);
}

errorClassName​

转发给 errorComponent 的 className

listen​

订阅处理函数,用于在 URL 位置变化等事件发生时重置错误状态。非常适合用边界包裹路由组件的场景。

下面是使用 Anansi Router 的示例,它使用了 history 订阅。

import { useRouter, Link, MatchedRoute } from '@anansi/router';
import { AsyncBoundary } from '@data-client/react';

function App() {
const { history } = useRouter();
return (
<div>
<nav>
<Link name="Home">Coin App</Link>
</nav>
<main>
<AsyncBoundary listen={history.listen}>
<MatchedRoute index={0} />
</AsyncBoundary>
</main>
</div>
);
}