<AsyncBoundary />
Trata as condições de carregamento e de erro do Suspense.
No React 18, isso cria uma divisão concorrente; no 16 e no 17, exibe fallbacks de carregamento. Se houver um erro irrecuperável, exibe um fallback de erro.
Saiba mais sobre o posicionamento de boundaries aprendendo a co-localizar dependências de dados
Uso
Coloque o AsyncBoundary nos limites de navegação ou acima deles, como páginas, rotas ou modais.
- React Router
- NextJS
- Expo
- Antd Modal
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>
);
}
import { AsyncBoundary } from '@data-client/react';
export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div>
<h1>Dashboard</h1>
<section>
<AsyncBoundary>{children}</AsyncBoundary>
</section>
</div>
);
}
import { AsyncBoundary } from '@data-client/react';
import { Slot } from 'expo-router';
import { Image, StyleSheet } from 'react-native';
import ParallaxScrollView from '@/components/ParallaxScrollView';
export default function DashboardLayout() {
return (
<ParallaxScrollView
headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }}
headerImage={
<Image
source={require('@/assets/images/my-logo.png')}
style={styles.logo}
/>
}
>
<AsyncBoundary>
<Slot />
</AsyncBoundary>
</ParallaxScrollView>
);
}
const styles = StyleSheet.create({
logo: { height: 178, width: 290 },
});
import { AsyncBoundary } from '@data-client/react';
import { useState } from 'react';
import { Button, Modal } from 'antd';
import MyModalBody from './MyModalBody';
export default function ModalOpen() {
const [isModalOpen, setIsModalOpen] = useState(false);
const showModal = () => setIsModalOpen(true);
const handleOk = () => setIsModalOpen(false);
const handleCancel = () => setIsModalOpen(false);
return (
<>
<Button type="primary" onClick={showModal}>
Open Modal
</Button>
<Modal title="Basic Modal" open={isModalOpen} onOk={handleOk} onCancel={handleCancel}>
<AsyncBoundary>
<MyModalBody />
</AsyncBoundary>
</Modal>
</>
);
}
Depois, use useSuspense() nos componentes que renderizam os dados. Quaisquer erros ou estados de carregamento
de qualquer descendente do <AsyncBoundary /> serão renderizados no <AsyncBoundary />. Essa consolidação
da UI de fallback melhora o desempenho e a usabilidade.
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
Qualquer elemento renderizável (React Node) a ser exibido durante o carregamento
errorComponent
Componente para tratar os erros capturados
Exemplo de fallback personalizado
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
className a ser repassado ao errorComponent
listen
Handler de assinatura para redefinir o estado de erro em eventos como mudanças na URL. É ótimo para posicionar um boundary que envolve componentes de roteamento.
Um exemplo usando o Anansi Router, que usa a assinatura do 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>
);
}