UNPKG

react-router

Version:

A complete routing library for React.js

131 lines (105 loc) 4.23 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); 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; }; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } var _react = require('react'); var _react2 = _interopRequireDefault(_react); function shallowEqual(a, b) { var ka = 0; var kb = 0; for (var key in a) { if (a.hasOwnProperty(key) && a[key] !== b[key]) return false; ka++; } for (var key in b) { if (b.hasOwnProperty(key)) kb++; }return ka === kb; } var AsyncProps = _react2['default'].createClass({ displayName: 'AsyncProps', statics: { createElement: function createElement(Component, state) { return Component.loadProps ? _react2['default'].createElement(AsyncProps, { Component: Component, routing: state }) : _react2['default'].createElement(Component, state); } }, getInitialState: function getInitialState() { return { propsAreLoading: false, propsAreLoadingLong: false, asyncProps: null, previousRoutingState: null }; }, componentDidMount: function componentDidMount() { this.load(this.props); }, componentWillReceiveProps: function componentWillReceiveProps(nextProps) { var _this = this; var needToLoad = !shallowEqual(nextProps.routing.routeParams, this.props.routing.routeParams); if (needToLoad) { var routerTransitioned = nextProps.routing.location !== this.props.routing.location; var keepPreviousRoutingState = this.state.propsAreLoadingLong && routerTransitioned; if (keepPreviousRoutingState) { this.load(nextProps); } else { this.setState({ previousRoutingState: this.props.routing }, function () { return _this.load(nextProps); }); } } }, /* * Could make this method much better, right now AsyncProps doesn't render its * children until it fetches data, causing a "waterfall" effect, when instead * it could look at the branch of components from it down to the end and load * up the props for all of them in parallel, waterfall will do for now... */ load: function load(props) { var _this2 = this; var lastLoadTime = this._lastLoadTime = Date.now(); var params = props.routing.params; var Component = this.props.Component; this.setState({ propsAreLoading: true }, function () { var longLoadTimer = setTimeout(function () { _this2.setState({ propsAreLoadingLong: true }); }, 300); // TODO: handle `error`s Component.loadProps(params, function (error, asyncProps) { clearTimeout(longLoadTimer); // if the router transitions between now and when the callback runs we will // ignore it to prevent setting state w/ the wrong data (earlier calls to // load that call back later than later calls to load) if (_this2._lastLoadTime !== lastLoadTime || !_this2.isMounted()) return; _this2.setState({ propsAreLoading: false, propsAreLoadingLong: false, asyncProps: asyncProps, previousRoutingState: null }); }); }); }, render: function render() { var _this3 = this; var Component = this.props.Component; var _state = this.state; var asyncProps = _state.asyncProps; var propsAreLoading = _state.propsAreLoading; var propsAreLoadingLong = _state.propsAreLoadingLong; var routing = this.state.previousRoutingState || this.props.routing; if (this.state.asyncProps === null) return Component.Loader ? _react2['default'].createElement(Component.Loader, routing) : null; return _react2['default'].createElement(Component, _extends({ onPropsDidChange: function () { return _this3.load(_this3.props); }, propsAreLoading: propsAreLoading, propsAreLoadingLong: propsAreLoadingLong }, routing, asyncProps)); } }); exports['default'] = AsyncProps; module.exports = exports['default'];