UNPKG

react-universal-component

Version:

A higher order component for loading components with promises

366 lines (287 loc) 13.2 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.setHasBabelPlugin = exports.ReportChunks = exports.MODULE_IDS = exports.CHUNK_NAMES = undefined; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _requireUniversalModule = require('./requireUniversalModule'); Object.defineProperty(exports, 'CHUNK_NAMES', { enumerable: true, get: function get() { return _requireUniversalModule.CHUNK_NAMES; } }); Object.defineProperty(exports, 'MODULE_IDS', { enumerable: true, get: function get() { return _requireUniversalModule.MODULE_IDS; } }); var _reportChunks = require('./report-chunks'); Object.defineProperty(exports, 'ReportChunks', { enumerable: true, get: function get() { return _interopRequireDefault(_reportChunks).default; } }); exports.default = universal; var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _hoistNonReactStatics = require('hoist-non-react-statics'); var _hoistNonReactStatics2 = _interopRequireDefault(_hoistNonReactStatics); var _requireUniversalModule2 = _interopRequireDefault(_requireUniversalModule); var _context = require('./context'); var _context2 = _interopRequireDefault(_context); var _utils = require('./utils'); var _helpers = require('./helpers'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } var hasBabelPlugin = false; var isHMR = function isHMR() { return ( // $FlowIgnore module.hot && (module.hot.data || module.hot.status() === 'apply') ); }; var setHasBabelPlugin = exports.setHasBabelPlugin = function setHasBabelPlugin() { hasBabelPlugin = true; }; function universal(asyncModule) { var _class, _temp; var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var userRender = opts.render, _opts$loading = opts.loading, Loading = _opts$loading === undefined ? _utils.DefaultLoading : _opts$loading, _opts$error = opts.error, Err = _opts$error === undefined ? _utils.DefaultError : _opts$error, _opts$minDelay = opts.minDelay, minDelay = _opts$minDelay === undefined ? 0 : _opts$minDelay, _opts$alwaysDelay = opts.alwaysDelay, alwaysDelay = _opts$alwaysDelay === undefined ? false : _opts$alwaysDelay, _opts$testBabelPlugin = opts.testBabelPlugin, testBabelPlugin = _opts$testBabelPlugin === undefined ? false : _opts$testBabelPlugin, _opts$loadingTransiti = opts.loadingTransition, loadingTransition = _opts$loadingTransiti === undefined ? true : _opts$loadingTransiti, options = _objectWithoutProperties(opts, ['render', 'loading', 'error', 'minDelay', 'alwaysDelay', 'testBabelPlugin', 'loadingTransition']); var renderFunc = userRender || (0, _utils.createDefaultRender)(Loading, Err); var isDynamic = hasBabelPlugin || testBabelPlugin; options.isDynamic = isDynamic; options.usesBabelPlugin = hasBabelPlugin; options.modCache = {}; options.promCache = {}; return _temp = _class = function (_React$Component) { _inherits(UniversalComponent, _React$Component); _createClass(UniversalComponent, [{ key: 'requireAsyncInner', value: function requireAsyncInner(requireAsync, props, state, isMount) { var _this2 = this; if (!state.mod && loadingTransition) { this.update({ mod: null, props: props }); // display `loading` during componentWillReceiveProps } var time = new Date(); requireAsync(props).then(function (mod) { var state = { mod: mod, props: props }; var timeLapsed = new Date() - time; if (timeLapsed < minDelay) { var extraDelay = minDelay - timeLapsed; return setTimeout(function () { return _this2.update(state, isMount); }, extraDelay); } _this2.update(state, isMount); }).catch(function (error) { return _this2.update({ error: error, props: props }); }); } }, { key: 'handleBefore', value: function handleBefore(isMount, isSync) { var isServer = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; if (this.props.onBefore) { var onBefore = this.props.onBefore; var info = { isMount: isMount, isSync: isSync, isServer: isServer }; onBefore(info); } } }, { key: 'handleAfter', value: function handleAfter(state, isMount, isSync, isServer) { var mod = state.mod, error = state.error; if (mod && !error) { (0, _hoistNonReactStatics2.default)(UniversalComponent, mod, { preload: true, preloadWeak: true }); if (this.props.onAfter) { var onAfter = this.props.onAfter; var info = { isMount: isMount, isSync: isSync, isServer: isServer }; onAfter(info, mod); } } else if (error && this.props.onError) { this.props.onError(error); } this.setState(state); } // $FlowFixMe }, { key: 'init', value: function init(props) { var _req = (0, _requireUniversalModule2.default)(asyncModule, options, props), addModule = _req.addModule, requireSync = _req.requireSync, requireAsync = _req.requireAsync, asyncOnly = _req.asyncOnly; var mod = void 0; try { mod = requireSync(props); } catch (error) { return (0, _helpers.__update)(props, { error: error, props: props }, this._initialized); } this._asyncOnly = asyncOnly; var chunkName = addModule(props); // record the module for SSR flushing :) if (this.context && this.context.report) { this.context.report(chunkName); } if (mod || _utils.isServer) { this.handleBefore(true, true, _utils.isServer); return (0, _helpers.__update)(props, { asyncOnly: asyncOnly, props: props, mod: mod }, this._initialized, true, true, _utils.isServer); } this.handleBefore(true, false); this.requireAsyncInner(requireAsync, props, { props: props, asyncOnly: asyncOnly, mod: mod }, true); return { mod: mod, asyncOnly: asyncOnly, props: props }; } }], [{ key: 'preload', value: function preload(props) { props = props || {}; var _req2 = (0, _requireUniversalModule2.default)(asyncModule, options, props), requireAsync = _req2.requireAsync, requireSync = _req2.requireSync; var mod = void 0; try { mod = requireSync(props); } catch (error) { return Promise.reject(error); } return Promise.resolve().then(function () { if (mod) return mod; return requireAsync(props); }).then(function (mod) { (0, _hoistNonReactStatics2.default)(UniversalComponent, mod, { preload: true, preloadWeak: true }); return mod; }); } /* eslint-enable react/sort-comp */ /* eslint-disable react/sort-comp */ }, { key: 'preloadWeak', value: function preloadWeak(props) { props = props || {}; var _req3 = (0, _requireUniversalModule2.default)(asyncModule, options, props), requireSync = _req3.requireSync; var mod = requireSync(props); if (mod) { (0, _hoistNonReactStatics2.default)(UniversalComponent, mod, { preload: true, preloadWeak: true }); } return mod; } }]); function UniversalComponent(props, context) { _classCallCheck(this, UniversalComponent); var _this = _possibleConstructorReturn(this, (UniversalComponent.__proto__ || Object.getPrototypeOf(UniversalComponent)).call(this, props, context)); _this.update = function (state) { var isMount = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var isSync = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var isServer = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; if (!_this._initialized) return; if (!state.error) state.error = null; _this.handleAfter(state, isMount, isSync, isServer); }; _this.state = _this.init(_this.props); // $FlowFixMe _this.state.error = null; return _this; } _createClass(UniversalComponent, [{ key: 'componentDidMount', value: function componentDidMount() { this._initialized = true; } }, { key: 'componentDidUpdate', value: function componentDidUpdate(prevProps) { var _this3 = this; if (isDynamic || this._asyncOnly) { var _req4 = (0, _requireUniversalModule2.default)(asyncModule, options, this.props, prevProps), requireSync = _req4.requireSync, requireAsync = _req4.requireAsync, shouldUpdate = _req4.shouldUpdate; if (shouldUpdate(this.props, prevProps)) { var mod = void 0; try { mod = requireSync(this.props); } catch (error) { return this.update({ error: error }); } this.handleBefore(false, !!mod); if (!mod) { return this.requireAsyncInner(requireAsync, this.props, { mod: mod }); } var state = { mod: mod }; if (alwaysDelay) { if (loadingTransition) this.update({ mod: null }); // display `loading` during componentWillReceiveProps setTimeout(function () { return _this3.update(state, false, true); }, minDelay); return; } this.update(state, false, true); } } } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { this._initialized = false; } }, { key: 'render', value: function render() { var _props = this.props, isLoading = _props.isLoading, userError = _props.error, props = _objectWithoutProperties(_props, ['isLoading', 'error']); var _state = this.state, mod = _state.mod, error = _state.error; return renderFunc(props, mod, isLoading, userError || error); } }], [{ key: 'getDerivedStateFromProps', value: function getDerivedStateFromProps(nextProps, currentState) { var _req5 = (0, _requireUniversalModule2.default)(asyncModule, options, nextProps, currentState.props), requireSync = _req5.requireSync, shouldUpdate = _req5.shouldUpdate; if (isHMR() && shouldUpdate(currentState.props, nextProps)) { var mod = requireSync(nextProps); return _extends({}, currentState, { mod: mod }); } return null; } }]); return UniversalComponent; }(_react2.default.Component), _class.contextType = _context2.default, _temp; }