react-router-4-compat
Version:
A wrapped version of react router 4 which compatible with react router 3
524 lines (447 loc) • 18.2 kB
JavaScript
;
exports.__esModule = true;
exports.default = exports.RoutePropType = exports.makePath = exports.createRoutes = void 0;
var _react = _interopRequireDefault(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _Switch = _interopRequireDefault(require("react-router/Switch"));
var _Route = _interopRequireDefault(require("react-router/Route"));
var _matchPath = _interopRequireDefault(require("react-router/matchPath"));
var _reactAsyncWrapper = require("react-async-wrapper");
var _utils = require("./utils");
var _withRouter = _interopRequireDefault(require("./withRouter"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _next(value) { step("next", value); } function _throw(err) { step("throw", err); } _next(); }); }; }
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; }
function _extends() { _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; }; return _extends.apply(this, arguments); }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var createState = function createState(match, location, history) {
return _objectSpread({
match: match,
location: location,
history: history
}, location);
};
var createPromiseFromCallback = function createPromiseFromCallback(state, callbackFunc) {
return new Promise(function (resolve, reject) {
callbackFunc(state, function (err, result) {
if (err) {
reject(err);
} else {
resolve(result);
}
});
});
};
var createRoutePropertyPromise = function createRoutePropertyPromise(state, staticValue, dynamicValue) {
if (staticValue) {
return staticValue;
}
if (dynamicValue) {
return createPromiseFromCallback(state, dynamicValue);
}
return null;
};
var createRoutePromise = function createRoutePromise(state, route) {
var component = route.component,
getComponent = route.getComponent,
indexRoute = route.indexRoute,
getIndexRoute = route.getIndexRoute,
childRoutes = route.childRoutes,
getChildRoutes = route.getChildRoutes;
return Promise.all([createRoutePropertyPromise(state, component, getComponent), createRoutePropertyPromise(state, indexRoute, getIndexRoute), createRoutePropertyPromise(state, childRoutes, getChildRoutes)]).then(function (_ref) {
var comp = _ref[0],
ir = _ref[1],
cr = _ref[2];
return _objectSpread({}, route, {
component: comp,
indexRoute: ir,
childRoutes: cr
});
});
};
var createRoutes = function createRoutes(routes, onError, routeStack) {
if (routeStack === void 0) {
routeStack = [];
}
return routes.map(function (_route) {
var path = _route.path,
component = _route.component,
getComponent = _route.getComponent,
indexRoute = _route.indexRoute,
getIndexRoute = _route.getIndexRoute,
childRoutes = _route.childRoutes,
getChildRoutes = _route.getChildRoutes,
onEnter = _route.onEnter,
exact = _route.exact;
if (!component && !getComponent && !onEnter) {
return null;
}
return _react.default.createElement(_Route.default, {
key: path || 0,
path: path,
exact: !!exact // eslint-disable-next-line react/no-children-prop
,
children: function children(props) {
var match = props.match,
location = props.location,
history = props.history;
var routeState = createState(match, location, history);
if (component && (indexRoute || !getIndexRoute) && (childRoutes || !getChildRoutes) && !onEnter) {
return _react.default.createElement(Route4Compat, _extends({}, props, {
state: routeState,
route: _route,
routeStack: routeStack,
onError: onError
}));
}
var asyncJobs = [];
if (onEnter) {
asyncJobs.push(function () {
return new Promise(function (resolve, reject) {
if (onEnter.length >= 3) {
onEnter(routeState, history.replace, function (err) {
if (err) {
reject(err);
} else {
resolve();
}
});
} else {
onEnter(routeState, history.replace);
resolve();
}
});
});
}
return _react.default.createElement(_reactAsyncWrapper.AsyncComponent, {
batch: true,
onError: onError,
asyncJobs: asyncJobs,
asyncProps: {
route: function route() {
return createRoutePromise(routeState, _route);
}
},
loadingComponent: function loadingComponent() {
return null;
},
reloadOnUpdate: false
}, _react.default.createElement(Route4Compat, _extends({}, props, {
routeStack: routeStack,
state: routeState,
onError: onError
})));
}
});
}).filter(function (v) {
return v;
});
};
exports.createRoutes = createRoutes;
var makePath = function makePath(base, path) {
if (!path) {
return base || '/';
}
if (path.startsWith('/')) {
return path;
}
return (base === '/' ? '' : base) + "/" + path;
};
exports.makePath = makePath;
var shallowEqual = function shallowEqual(obj1, obj2) {
if (obj1 === obj2) {
return true;
}
if (!obj1 || !obj2) {
return false;
}
var keys1 = Object.keys(obj1);
var keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) {
return false;
}
for (var i = 0; i < keys1.length; ++i) {
var key = keys1[i];
if (obj1[key] !== obj2[key]) {
return false;
}
}
return true;
};
var Route4Compat =
/*#__PURE__*/
function (_React$Component) {
function Route4Compat() {
return _React$Component.apply(this, arguments) || this;
}
var _proto = Route4Compat.prototype;
_proto.componentWillMount = function componentWillMount() {
this.context.routesCompat = this.props.routeStack.concat([this.props.route]);
this.context.routesUpdater(this.context.routesCompat);
};
_proto.componentWillReceiveProps = function componentWillReceiveProps(nextProps, ignored) {
var _this$props = this.props,
route = _this$props.route,
state = _this$props.state,
history = _this$props.history,
onError = _this$props.onError;
var onChange = route.onChange;
if (onChange) {
if (onChange.length >= 4) {
new Promise(function (resolve, reject) {
onChange(state, nextProps.state, history.replace, function (err) {
if (err) {
reject(err);
} else {
resolve();
}
});
}).catch(onError);
} else {
try {
onChange(state, nextProps.state, history.replace);
} catch (e) {
onError(e);
}
}
}
};
_proto.shouldComponentUpdate = function shouldComponentUpdate(nextProps, nextState, nextContext) {
// noinspection JSUnusedLocalSymbols
var nextMatch = nextProps.match,
nextParams = nextProps.params,
nState = nextProps.state,
nextRoute = nextProps.route,
nextRouteStack = nextProps.routeStack,
nextRest = _objectWithoutProperties(nextProps, ["match", "params", "state", "route", "routeStack"]); // noinspection JSUnusedLocalSymbols
var _this$props2 = this.props,
thisMatch = _this$props2.match,
thisParams = _this$props2.params,
tState = _this$props2.state,
thisRoute = _this$props2.route,
thisRouteStack = _this$props2.routeStack,
thisRest = _objectWithoutProperties(_this$props2, ["match", "params", "state", "route", "routeStack"]);
var _ref2 = nextMatch || {},
nextMatchParams = _ref2.params,
nextMatchRest = _objectWithoutProperties(_ref2, ["params"]);
var _ref3 = thisMatch || {},
thisMatchParams = _ref3.params,
thisMatchRest = _objectWithoutProperties(_ref3, ["params"]);
return !shallowEqual(this.state, nextState) || !shallowEqual(this.context, nextContext) || !shallowEqual(thisMatchParams, nextMatchParams) || !shallowEqual(thisMatchRest, nextMatchRest) || !shallowEqual(thisRoute, nextRoute) || !shallowEqual(thisRouteStack, nextRouteStack) || !shallowEqual(thisRest, nextRest);
};
_proto.componentWillUnmount = function componentWillUnmount() {
var _this$props3 = this.props,
route = _this$props3.route,
state = _this$props3.state,
onError = _this$props3.onError;
var onLeave = route.onLeave;
if (onLeave) {
try {
onLeave(state);
} catch (e) {
onError(e);
}
}
};
_proto.render = function render() {
var _this$props4 = this.props,
_route2 = _this$props4.route,
routeStack = _this$props4.routeStack,
state = _this$props4.state,
onError = _this$props4.onError,
rest = _objectWithoutProperties(_this$props4, ["route", "routeStack", "state", "onError"]);
var path = _route2.path,
Comp = _route2.component,
indexRoute = _route2.indexRoute;
if (!Comp) {
return null;
}
var childRoutes = _route2.childRoutes;
if ((0, _utils.some)(childRoutes, function (childRoute) {
return !childRoute.components && childRoute.getComponents;
})) {
// noinspection RequiredAttributes
return _react.default.createElement(_reactAsyncWrapper.AsyncComponent, {
batch: true,
onError: onError,
loadingComponent: function loadingComponent() {
return null;
},
asyncProps: {
route: function () {
var _route3 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee() {
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
return _context.abrupt("return", Promise.all((childRoutes || []).map(function (childRoute) {
if (childRoute.components || !childRoute.getComponents) {
return {
childRoute: childRoute
};
} else {
return new Promise(function (resolve, reject) {
return childRoute.getComponents(state, function (err, res) {
if (err) {
reject(err);
} else {
resolve({
childRoute: childRoute,
components: res
});
}
});
});
}
})).then(function (subComponents) {
return _objectSpread({}, _route2, {
childRoutes: subComponents.map(function (_ref4) {
var childRoute = _ref4.childRoute,
components = _ref4.components;
return _objectSpread({}, childRoute, {
components: components
});
})
});
}));
case 1:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
return function route() {
return _route3.apply(this, arguments);
};
}()
},
reloadOnUpdate: false
}, _react.default.createElement(Route4Compat, _extends({
routeStack: routeStack,
state: state,
onError: onError
}, rest)));
}
var components = {};
if (childRoutes) {
childRoutes = childRoutes.map(function (childRoute) {
var childPath = childRoute.path;
if (!childPath.startsWith('/')) {
return _objectSpread({}, childRoute, {
path: makePath(path, childPath)
});
}
return childRoute;
});
var _loop = function _loop(i) {
var childRoute = childRoutes[i];
var childComponents = childRoute.components;
if (childComponents) {
(0, _utils.assignWith)(components, childComponents, function (objValue, srcValue) {
if (!objValue) {
return [{
path: childRoute.path,
component: srcValue
}];
} else {
objValue.push({
path: childRoute.path,
component: srcValue
});
return objValue;
}
});
}
};
for (var i = 0; i < childRoutes.length; ++i) {
_loop(i);
}
}
var routes;
var routesCompat = this.context.routesCompat;
if (indexRoute) {
routes = [_objectSpread({}, indexRoute, {
path: makePath(path, indexRoute.path),
exact: true
})].concat(childRoutes || []);
} else {
routes = (childRoutes || []).concat();
}
var comps = (0, _utils.mapValues)(components, function (compRoutes) {
return function (props) {
if (compRoutes.length === 1) {
return _react.default.createElement(_Route.default, _extends({}, props, {
path: compRoutes[0].path,
component: (0, _withRouter.default)(compRoutes[0].component)
}));
} else {
return _react.default.createElement(_Switch.default, null, compRoutes.map(function (compRoute) {
return _react.default.createElement(_Route.default, _extends({}, props, {
path: compRoute.path,
component: (0, _withRouter.default)(compRoute.component)
}));
}));
}
};
});
var validRoutes = routes.filter(function (r) {
return !!(0, _matchPath.default)(state.location.pathname, r, state.match);
});
return validRoutes.length > 0 ? _react.default.createElement(Comp, _extends({}, rest, {
router: state.history,
params: state.match.params,
location: state.location,
routes: routesCompat
}, comps), createRoutes([validRoutes[0]], onError, routeStack.concat([_route2]))) : _react.default.createElement(Comp, _extends({}, rest, {
router: state.history,
params: state.match.params,
location: state.location,
routes: routesCompat
}, comps));
};
_inheritsLoose(Route4Compat, _React$Component);
return Route4Compat;
}(_react.default.Component);
Route4Compat.contextTypes = {
router: _propTypes.default.object
};
var RoutePropType = _propTypes.default.shape({
path: _propTypes.default.string,
component: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object]),
getComponent: _propTypes.default.func,
indexRoute: _propTypes.default.object,
getIndexRoute: _propTypes.default.func,
childRoutes: _propTypes.default.arrayOf(_propTypes.default.object),
getChildRoutes: _propTypes.default.func,
onLeave: _propTypes.default.func,
onChange: _propTypes.default.func,
exact: _propTypes.default.bool,
strict: _propTypes.default.bool,
sensitive: _propTypes.default.bool
});
exports.RoutePropType = RoutePropType;
Route4Compat.propTypes = {
route: RoutePropType,
routeStack: _propTypes.default.arrayOf(RoutePropType),
onError: _propTypes.default.func,
state: _propTypes.default.object
};
Route4Compat.defaultProps = {
route: {},
routeStack: [],
onError: function onError() {
return null;
},
state: {}
};
Route4Compat.contextTypes = {
routesCompat: _propTypes.default.arrayOf(RoutePropType),
routesUpdater: _propTypes.default.func
};
var _default = Route4Compat;
exports.default = _default;