用于渲染 promise 值,并自动处理错误。
注意: <Await>
需要在 <React.Suspense>
内部渲染。
import { Await, useLoaderData } from "react-router";
export async function loader() {
// not awaited
const reviews = getReviews();
// awaited (blocks the transition)
const book = await fetch("/api/book").then((res) => res.json());
return { book, reviews };
}
function Book() {
const { book, reviews } = useLoaderData();
return (
<div>
<h1>{book.title}</h1>
<p>{book.description}</p>
<React.Suspense fallback={<ReviewsSkeleton />}>
<Await
resolve={reviews}
errorElement={
<div>Could not load reviews 😬</div>
}
children={(resolvedReviews) => (
<Reviews items={resolvedReviews} />
)}
/>
</React.Suspense>
</div>
);
}
function Await<Resolve>({
children,
errorElement,
resolve,
}: AwaitProps<Resolve>)
当使用函数时,解析出的值将作为参数提供。
<Await resolve={reviewsPromise}>
{(resolvedReviews) => <Reviews items={resolvedReviews} />}
</Await>
当使用 React 元素时,useAsyncValue
将提供解析出的值。
<Await resolve={reviewsPromise}>
<Reviews />
</Await>
function Reviews() {
const resolvedReviews = useAsyncValue();
return <div>...</div>;
}
当 Promise
被拒绝时,将渲染错误元素而不是 children
。
<Await
errorElement={<div>Oops</div>}
resolve={reviewsPromise}
>
<Reviews />
</Await>
要提供更具上下文的错误,您可以在子组件中使用 useAsyncError
。
<Await
errorElement={<ReviewsError />}
resolve={reviewsPromise}
>
<Reviews />
</Await>
function ReviewsError() {
const error = useAsyncError();
return <div>Error loading reviews: {error.message}</div>;
}
如果您不提供 errorElement
,被拒绝的值将冒泡到最近的路由级别 ErrorBoundary
,并可通过 useRouteError
hook 访问。
接收从 loader
返回的 Promise
,待其解析并渲染。
import { Await, useLoaderData } from "react-router";
export async function loader() {
let reviews = getReviews(); // not awaited
let book = await getBook();
return {
book,
reviews, // this is a promise
};
}
export default function Book() {
const {
book,
reviews, // this is the same promise
} = useLoaderData();
return (
<div>
<h1>{book.title}</h1>
<p>{book.description}</p>
<React.Suspense fallback={<ReviewsSkeleton />}>
<Await
// and is the promise we pass to Await
resolve={reviews}
>
<Reviews />
</Await>
</React.Suspense>
</div>
);
}