UNPKG

reactmvc

Version:

M(immutable model)V(view component)C(react-router)

296 lines (251 loc) 11.4 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.loadPropsOnServer = 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 _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; /* eslint-disable react/no-multi-comp, import/no-unresolved */ var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _RouterContext = require('react-router/lib/RouterContext'); var _RouterContext2 = _interopRequireDefault(_RouterContext); 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 eachComponents(components, iterator) { components.forEach(function (value) { if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object') { var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = value[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var component = _step.value; iterator(component); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } else { iterator(value); } }); } function findAsyncComponents(components) { var asyncComponents = []; eachComponents(components, function (component) { if (component.loadProps) { asyncComponents.push(component); } }); return asyncComponents; } function _loadAsyncProps(components, params, location) { var componentArray = []; var propsArray = []; var tasks = findAsyncComponents(components).map(function (component, index) { return Promise.resolve().then(function () { return component.loadProps(params, location); }).then(function (props) { propsArray[index] = props; componentArray[index] = component; }); }); return Promise.all(tasks).then(function () { return { componentArray: componentArray, propsArray: propsArray }; }); } function lookupPropsForComponent(component, propsAndComponents) { var componentArray = propsAndComponents.componentArray; var propsArray = propsAndComponents.propsArray; var index = componentArray.indexOf(component); return propsArray[index]; } function _createElement(component, routerProps, asyncInfo) { if (component.loadProps) { return _react2.default.createElement(AsyncPropsContainer, { component: component, routerProps: routerProps, asyncInfo: asyncInfo }); } return _react2.default.createElement(component, routerProps); } var AsyncPropsContainer = function (_Component) { _inherits(AsyncPropsContainer, _Component); function AsyncPropsContainer() { _classCallCheck(this, AsyncPropsContainer); return _possibleConstructorReturn(this, (AsyncPropsContainer.__proto__ || Object.getPrototypeOf(AsyncPropsContainer)).apply(this, arguments)); } _createClass(AsyncPropsContainer, [{ key: 'render', value: function render() { var _props = this.props; var component = _props.component; var routerProps = _props.routerProps; var asyncInfo = _props.asyncInfo; var propsAndComponents = asyncInfo.propsAndComponents; var loading = asyncInfo.loading; var reload = asyncInfo.reload; var routeChanged = asyncInfo.routeChanged; var asyncProps = lookupPropsForComponent(component, propsAndComponents); var props = _extends({}, routerProps, asyncProps, { reload: reload, loading: loading, routeChanged: routeChanged }); return _react2.default.createElement(component, props); } }]); return AsyncPropsContainer; }(_react.Component); AsyncPropsContainer.propTypes = { component: _react.PropTypes.func.isRequired, routerProps: _react.PropTypes.object.isRequired, asyncInfo: _react.PropTypes.object.isRequired }; var AsyncProps = function (_Component2) { _inherits(AsyncProps, _Component2); function AsyncProps(props, context) { _classCallCheck(this, AsyncProps); var _this2 = _possibleConstructorReturn(this, (AsyncProps.__proto__ || Object.getPrototypeOf(AsyncProps)).call(this, props, context)); var propsArray = props.propsArray; var componentArray = props.componentArray; var isServerRender = propsArray && componentArray; _this2.state = { loading: false, prevProps: null, propsAndComponents: isServerRender ? { propsArray: propsArray, componentArray: componentArray } : null, routeChanged: false, routeChangeError: false }; return _this2; } _createClass(AsyncProps, [{ key: 'componentWillMount', value: function componentWillMount() { var _props2 = this.props; var components = _props2.components; var params = _props2.params; var location = _props2.location; this.loadAsyncProps(components, params, location); } }, { key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps) { var routeChanged = nextProps.location.key !== this.props.location.key; if (routeChanged) { var components = nextProps.components; var params = nextProps.params; var location = nextProps.location; this.loadAsyncProps(components, params, location); } } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { this.unmounted = true; } }, { key: 'loadAsyncProps', value: function loadAsyncProps(components, params, location) { var _this3 = this; var routeChanged = location.key !== this.props.location.key; this.setState({ loading: true, prevProps: this.props, routeChanged: routeChanged }); var onError = this.props.onError; return _loadAsyncProps(components, params, location).then(function (propsAndComponents) { var sameLocation = _this3.props.location.key === location.key; if (sameLocation && !_this3.unmounted) { _this3.setState({ loading: false, prevProps: null, propsAndComponents: propsAndComponents, routeChangeError: false }); } }).catch(function (err) { var sameLocation = _this3.props.location.key === location.key; var _state = _this3.state; var routeChangeError = _state.routeChangeError; var propsAndComponents = _state.propsAndComponents; if (sameLocation && !_this3.unmounted) { _this3.setState({ loading: false, routeChangeError: routeChangeError || routeChanged || !propsAndComponents }); } onError(err); }); } }, { key: 'reload', value: function reload(actionName) { if (process.env.NODE_ENV !== 'production') { for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } console.info(actionName, args); // eslint-disable-line no-console } var _props3 = this.props; var components = _props3.components; var params = _props3.params; var location = _props3.location; return this.loadAsyncProps(components, params, location); } }, { key: 'render', value: function render() { var _state2 = this.state; var loading = _state2.loading; var prevProps = _state2.prevProps; var propsAndComponents = _state2.propsAndComponents; var routeChanged = _state2.routeChanged; var routeChangeError = _state2.routeChangeError; var _props4 = this.props; var renderLoading = _props4.renderLoading; var renderErrorPage = _props4.renderErrorPage; if (routeChangeError) { return renderErrorPage(); } if (!propsAndComponents) { return renderLoading(); } var asyncInfo = { loading: loading, routeChanged: routeChanged, propsAndComponents: propsAndComponents, reload: this.reload.bind(this) }; var props = prevProps || this.props; return _react2.default.createElement(_RouterContext2.default, _extends({}, props, { createElement: function createElement(component, routerProps) { return _createElement(component, routerProps, asyncInfo); } })); } }]); return AsyncProps; }(_react.Component); AsyncProps.propTypes = { components: _react2.default.PropTypes.array.isRequired, params: _react2.default.PropTypes.object.isRequired, location: _react2.default.PropTypes.object.isRequired, onError: _react2.default.PropTypes.func.isRequired, renderLoading: _react2.default.PropTypes.func.isRequired, renderErrorPage: _react2.default.PropTypes.func.isRequired, // server rendering propsArray: _react2.default.PropTypes.array, componentArray: _react2.default.PropTypes.array }; AsyncProps.defaultProps = { onError: function onError(err) { throw err; }, renderLoading: function renderLoading() { return null; }, renderErrorPage: function renderErrorPage() { return null; } }; var loadPropsOnServer = exports.loadPropsOnServer = function loadPropsOnServer(_ref) { var components = _ref.components; var params = _ref.params; var location = _ref.location; return _loadAsyncProps(components, params, location); }; exports.default = AsyncProps;