48 lines
1.5 KiB
TypeScript
48 lines
1.5 KiB
TypeScript
import React, {
|
|
lazy, Suspense, useMemo, useState, useEffect,
|
|
} from 'react';
|
|
import cloneDeep from 'lodash/cloneDeep';
|
|
import Skeleton from '@material-ui/lab/Skeleton';
|
|
import Loading from '@Components/Base/Loading';
|
|
import { Props, ComponentState } from './types';
|
|
|
|
const Components: { [key: string]: ComponentState } = {};
|
|
|
|
const Lazy: React.FC<Props> = (props): React.ReactElement => {
|
|
const { componentImport, componentChunkName, componentProps } = props;
|
|
const [isRender, setIsRender] = useState(false);
|
|
const RenderComponent = useMemo(() => {
|
|
const Component = Components[componentChunkName];
|
|
if (Component) {
|
|
return <Component {...componentProps} />;
|
|
}
|
|
return (
|
|
<div style={{ width: '100%', height: '100%' }}>
|
|
<Loading typePosition="relative" typeZIndex={10005} typeIcon="line:fix" isLoading />
|
|
<Skeleton variant="rect" width="100%" height="100%" animation="wave" />
|
|
</div>
|
|
);
|
|
}, [componentChunkName, isRender, componentProps]);
|
|
/* Hooks */
|
|
useEffect(() => {
|
|
(async () => {
|
|
if (!Components[componentChunkName]) {
|
|
Components[componentChunkName] = lazy(async () => {
|
|
const Element = await componentImport;
|
|
return Element;
|
|
});
|
|
}
|
|
setIsRender(cloneDeep(!isRender));
|
|
})();
|
|
}, [componentChunkName]);
|
|
return (
|
|
<React.Fragment>
|
|
<Suspense fallback={<Loading typePosition="relative" typeZIndex={10005} typeIcon="line:fix" isLoading />}>
|
|
{RenderComponent}
|
|
</Suspense>
|
|
</React.Fragment>
|
|
);
|
|
};
|
|
|
|
export default Lazy;
|