import React from "react"; import PropTypes from "prop-types"; import warning from "tiny-warning"; import HistoryContext from "./HistoryContext.js"; import RouterContext from "./RouterContext.js"; /** * The public API for putting history on context. */ class Router extends React.Component { static computeRootMatch(pathname) { return { path: "/", url: "/", params: {}, isExact: pathname === "/" }; } constructor(props) { super(props); this.state = { location: props.history.location }; // This is a bit of a hack. We have to start listening for location // changes here in the constructor in case there are any s // on the initial render. If there are, they will replace/push when // they mount and since cDM fires in children before parents, we may // get a new location before the is mounted. this._isMounted = false; this._pendingLocation = null; if (!props.staticContext) { this.unlisten = props.history.listen(location => { this._pendingLocation = location; }); } } componentDidMount() { this._isMounted = true; if (this.unlisten) { // Any pre-mount location changes have been captured at // this point, so unregister the listener. this.unlisten(); } if (!this.props.staticContext) { this.unlisten = this.props.history.listen(location => { if (this._isMounted) { this.setState({ location }); } }); } if (this._pendingLocation) { this.setState({ location: this._pendingLocation }); } } componentWillUnmount() { if (this.unlisten) { this.unlisten(); this._isMounted = false; this._pendingLocation = null; } } render() { return ( ); } } if (__DEV__) { Router.propTypes = { children: PropTypes.node, history: PropTypes.object.isRequired, staticContext: PropTypes.object }; Router.prototype.componentDidUpdate = function(prevProps) { warning( prevProps.history === this.props.history, "You cannot change " ); }; } export default Router;