1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- 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 <Redirect>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 <Router> is mounted.
- this._isMounted = false;
- this._pendingLocation = null;
- if (!props.staticContext) {
- this.unlisten = props.history.listen(location => {
- if (this._isMounted) {
- this.setState({ location });
- } else {
- this._pendingLocation = location;
- }
- });
- }
- }
- componentDidMount() {
- this._isMounted = true;
- if (this._pendingLocation) {
- this.setState({ location: this._pendingLocation });
- }
- }
- componentWillUnmount() {
- if (this.unlisten) {
- this.unlisten();
- this._isMounted = false;
- this._pendingLocation = null;
- }
- }
- render() {
- return (
- <RouterContext.Provider
- value={{
- history: this.props.history,
- location: this.state.location,
- match: Router.computeRootMatch(this.state.location.pathname),
- staticContext: this.props.staticContext
- }}
- >
- <HistoryContext.Provider
- children={this.props.children || null}
- value={this.props.history}
- />
- </RouterContext.Provider>
- );
- }
- }
- 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 <Router history>"
- );
- };
- }
- export default Router;
|