UNPKG

@caixue/react-loadable

Version:

A higher order component for loading components with dynamic imports.Support vite and webpack.

190 lines (189 loc) 8.98 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var _a; Object.defineProperty(exports, "__esModule", { value: true }); const react_1 = __importDefault(require("react")); const forwardRefSymbol = react_1.default.forwardRef(() => null).$$typeof; const style = { color: '#fff', background: '#499af2', borderColor: '#499af2', cursor: 'pointer', lineHeight: '34px', padding: '0 10px', boxSizing: 'border-box', borderRadius: '3px' }; const lang = (_a = window.document.getElementsByTagName('html')[0]) === null || _a === void 0 ? void 0 : _a.getAttribute('lang'); const Loading = (props) => { const isZh_CN = lang === 'zh-CN'; if (props.isError) { return react_1.default.createElement("div", null, isZh_CN ? '加载错误!' : 'Load error!', " ", react_1.default.createElement("button", { style: style, onClick: props.retry }, isZh_CN ? '重试' : 'Retry')); } else if (props.isTimedOut) { return react_1.default.createElement("div", null, isZh_CN ? '响应时间过长...' : 'Take a long time...', " ", react_1.default.createElement("button", { style: style, onClick: props.retry }, isZh_CN ? '重试' : 'Retry')); } else if (props.isLoading) { return react_1.default.createElement("div", null, isZh_CN ? '正在加载文件...' : 'Loading file...'); } else { return null; } }; const ALL_INITIALIZERS = []; const READY_INITIALIZERS = []; // T is loader component's propsType function Loadable(option) { var _a; var _AsyncCom_refPromise, _AsyncCom_resolveRef, _b; let importComponent, delay, loading = Loading, timeout = 10000; if (typeof option === 'function') { importComponent = option; } else { importComponent = option.loader; delay = option.delay; loading = option.loading || Loading; timeout = (_a = option.timeout) !== null && _a !== void 0 ? _a : timeout; } return _b = class AsyncCom extends react_1.default.Component { constructor(props) { super(props); // React.ComponentClass<T> | /** '#' start means private property */ _AsyncCom_refPromise.set(this, void 0); _AsyncCom_resolveRef.set(this, void 0); this.state = { isLoading: false, isError: false, isTimedOut: false, }; this.getComponent = this.getComponent.bind(this); this.handleRes = this.handleRes.bind(this); __classPrivateFieldSet(this, _AsyncCom_refPromise, new Promise(resolve => { __classPrivateFieldSet(this, _AsyncCom_resolveRef, resolve, "f"); }), "f"); } getComponent() { return __awaiter(this, void 0, void 0, function* () { const index = ALL_INITIALIZERS.indexOf(importComponent); this.setState({ isLoading: true, }); if (delay) { yield new Promise(r => { setTimeout(r, delay); }); } const p = Promise.race([importComponent().catch(e => { process.env.NODE_ENV === 'development' && console.error(e); return { isError: true }; }), new Promise(r => { setTimeout(() => { r({ isTimedOut: true }); }, timeout); })]); if (index === -1) { ALL_INITIALIZERS.push(importComponent); READY_INITIALIZERS.push(p); } else { READY_INITIALIZERS[index] = p; } const res = yield p; this.handleRes(res); }); } componentDidMount() { return __awaiter(this, void 0, void 0, function* () { const index = ALL_INITIALIZERS.indexOf(importComponent); if (index !== -1) { const res = yield READY_INITIALIZERS[index]; this.handleRes(res); } else { if (this.state.Component) return; this.getComponent(); } }); } componentWillUnmount() { this.setState = () => false; } handleRes(res) { const { isTimedOut, isError, default: Component } = res; if (isTimedOut) { this.setState({ isTimedOut: true, isLoading: false, isError: false, }); } else if (isError) { this.setState({ isError: true, isTimedOut: false, isLoading: false, }); } else { this.setState({ // component: <Component {...this.props} />, Component, isLoading: false, isError: false, isTimedOut: false, }); } } /** get resolve component ref */ getRef() { return __awaiter(this, void 0, void 0, function* () { return __classPrivateFieldGet(this, _AsyncCom_refPromise, "f"); }); } render() { const Loading = loading; const { isError, isLoading, isTimedOut, Component } = this.state; return (Component //@ts-ignore ? ((Component.$$typeof === forwardRefSymbol || react_1.default.Component.isPrototypeOf(Component)) ? react_1.default.createElement(Component, Object.assign({}, this.props, { ref: (ref) => __classPrivateFieldGet(this, _AsyncCom_resolveRef, "f").call(this, ref) })) : react_1.default.createElement(Component, Object.assign({}, this.props))) : react_1.default.createElement(Loading, { isError: isError, isLoading: isLoading, isTimedOut: isTimedOut, retry: this.getComponent })); } }, _AsyncCom_refPromise = new WeakMap(), _AsyncCom_resolveRef = new WeakMap(), _b; } exports.default = Loadable;