react-imported-component
Version:
I will import your component, and help to handle it
62 lines (61 loc) • 2.47 kB
JavaScript
import * as React from 'react';
import { useMemo } from 'react';
import { getLoadable } from '../loadable/loadable';
import { isBackend } from '../utils/detectBackend';
import { asDefault } from '../utils/utils';
import { ImportedComponent } from './Component';
import { useLoadable } from './useImported';
/**
* creates a "lazy" component, like `React.lazy`
* @see {@link useImported} or {@link useLazy}
* @param {Function} loaderFunction - () => import('a'), or () => require('b')
* @param {Object} [options]
* @param {React.Component} [options.LoadingComponent]
* @param {React.Component} [options.ErrorComponent]
* @param {Function} [options.onError] - error handler. Will consume the real error.
* @param {Function} [options.async = false] - enable React 16+ suspense.
*
* @example
* const PageA = imported('./pageA', { async: true });
*/
function loader(loaderFunction, baseOptions = {}) {
let loadable = getLoadable(loaderFunction);
const Imported = React.forwardRef(function ImportedComponentHOC({ importedProps = {}, ...props }, ref) {
const options = { ...baseOptions, ...importedProps };
// re-get loadable in order to have fresh reference
loadable = getLoadable(loaderFunction);
return (React.createElement(ImportedComponent, { loadable: loadable, LoadingComponent: options.LoadingComponent, ErrorComponent: options.ErrorComponent, onError: options.onError, render: options.render, async: options.async, forwardProps: props || {}, forwardRef: ref }));
});
Imported.preload = () => {
loadable.load().catch(() => ({}));
return loadable.resolution;
};
Object.defineProperty(Imported, 'done', {
get() {
return loadable.resolution;
},
});
return Imported;
}
const ReactLazy = React.lazy;
/**
* React.lazy "as-is" replacement
*/
export function lazy(importer) {
if (isBackend) {
return loader(importer);
}
if (process.env.NODE_ENV !== 'production') {
// lazy is not hot-reloadable
if (module.hot) {
return loader(importer, { async: true });
}
}
const topLoadable = getLoadable(importer);
return function ImportedLazy(props) {
const { loadable } = useLoadable(topLoadable);
const Lazy = useMemo(() => ReactLazy(() => loadable.tryResolveSync(asDefault)), [loadable]);
return React.createElement(Lazy, { ...props });
};
}
export default loader;