-
-
Notifications
You must be signed in to change notification settings - Fork 185
/
AsyncPreviewComponent.tsx
48 lines (40 loc) · 1.3 KB
/
AsyncPreviewComponent.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import { Skeleton } from "@mui/material";
import * as React from "react";
import { useEffect, useState } from "react";
export interface AsyncPreviewComponentProps {
builder: Promise<React.ReactNode>;
}
/**
* Utility component used to render the result of an async execution.
* It shows a loading indicator while at it.
*
* @category Preview components
*/
export const AsyncPreviewComponent = React.memo(AsyncPreviewComponentInternal) as React.FunctionComponent<AsyncPreviewComponentProps>;
function AsyncPreviewComponentInternal<M extends { [Key: string]: any }>(
{
builder
}: AsyncPreviewComponentProps): JSX.Element {
const [loading, setLoading] = useState<boolean>(true);
const [result, setResult] = useState<React.ReactNode>(null);
useEffect(() => {
let unmounted = false;
builder
.then((res) => {
if (!unmounted) {
setLoading(false);
setResult(res);
}
})
.catch(error => {
setLoading(false);
console.error(error);
});
return () => {
unmounted = true;
};
}, [builder]);
if (loading)
return <Skeleton variant="text"/>;
return <React.Fragment>{result}</React.Fragment>;
}