UNPKG

2.24 kBJavaScriptView Raw
1import React from "react";
2import PropTypes from "prop-types";
3import warning from "tiny-warning";
4
5import HistoryContext from "./HistoryContext.js";
6import RouterContext from "./RouterContext.js";
7
8/**
9 * The public API for putting history on context.
10 */
11class Router extends React.Component {
12 static computeRootMatch(pathname) {
13 return { path: "/", url: "/", params: {}, isExact: pathname === "/" };
14 }
15
16 constructor(props) {
17 super(props);
18
19 this.state = {
20 location: props.history.location
21 };
22
23 // This is a bit of a hack. We have to start listening for location
24 // changes here in the constructor in case there are any <Redirect>s
25 // on the initial render. If there are, they will replace/push when
26 // they mount and since cDM fires in children before parents, we may
27 // get a new location before the <Router> is mounted.
28 this._isMounted = false;
29 this._pendingLocation = null;
30
31 if (!props.staticContext) {
32 this.unlisten = props.history.listen(location => {
33 if (this._isMounted) {
34 this.setState({ location });
35 } else {
36 this._pendingLocation = location;
37 }
38 });
39 }
40 }
41
42 componentDidMount() {
43 this._isMounted = true;
44
45 if (this._pendingLocation) {
46 this.setState({ location: this._pendingLocation });
47 }
48 }
49
50 componentWillUnmount() {
51 if (this.unlisten) this.unlisten();
52 }
53
54 render() {
55 return (
56 <RouterContext.Provider
57 value={{
58 history: this.props.history,
59 location: this.state.location,
60 match: Router.computeRootMatch(this.state.location.pathname),
61 staticContext: this.props.staticContext
62 }}
63 >
64 <HistoryContext.Provider
65 children={this.props.children || null}
66 value={this.props.history}
67 />
68 </RouterContext.Provider>
69 );
70 }
71}
72
73if (__DEV__) {
74 Router.propTypes = {
75 children: PropTypes.node,
76 history: PropTypes.object.isRequired,
77 staticContext: PropTypes.object
78 };
79
80 Router.prototype.componentDidUpdate = function(prevProps) {
81 warning(
82 prevProps.history === this.props.history,
83 "You cannot change <Router history>"
84 );
85 };
86}
87
88export default Router;