<AsyncBoundary />
Maneja los estados de carga y error de Suspense.
En React 18 esto creará una división concurrente, y en 16 y 17 mostrará fallbacks de carga. Si hay un error irrecuperable, mostrará un fallback de error.
Aprende más sobre dónde colocar los límites viendo cómo colocalizar las dependencias de datos
Uso
Coloca AsyncBoundary en o por encima de los límites de navegación como páginas, rutas o modales.
- 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>
</>
);
}
Luego usa useSuspense() en los componentes que renderizan los datos. Cualquier error o estado de carga
de cualquier descendiente del <AsyncBoundary /> se renderizará en el <AsyncBoundary />. Esta consolidación
de la interfaz de fallback mejora el rendimiento y la usabilidad.
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
Cualquier elemento renderizable (React Node) que se muestra mientras carga
errorComponent
Componente que maneja los errores capturados
Ejemplo 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 que se reenvía a errorComponent
listen
Manejador de suscripción para restablecer el estado de error ante eventos como los cambios de ubicación de la URL. Es ideal para colocar un límite que envuelva los componentes de enrutamiento.
Un ejemplo con Anansi Router, que usa la suscripción de 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>
);
}