1 | import React from "react";
|
2 | import PropTypes from "prop-types";
|
3 | import warning from "tiny-warning";
|
4 |
|
5 | import HistoryContext from "./HistoryContext.js";
|
6 | import RouterContext from "./RouterContext.js";
|
7 |
|
8 |
|
9 |
|
10 |
|
11 | class 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 |
|
24 |
|
25 |
|
26 |
|
27 |
|
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) {
|
52 | this.unlisten();
|
53 | this._isMounted = false;
|
54 | this._pendingLocation = null;
|
55 | }
|
56 | }
|
57 |
|
58 | render() {
|
59 | return (
|
60 | <RouterContext.Provider
|
61 | value={{
|
62 | history: this.props.history,
|
63 | location: this.state.location,
|
64 | match: Router.computeRootMatch(this.state.location.pathname),
|
65 | staticContext: this.props.staticContext
|
66 | }}
|
67 | >
|
68 | <HistoryContext.Provider
|
69 | children={this.props.children || null}
|
70 | value={this.props.history}
|
71 | />
|
72 | </RouterContext.Provider>
|
73 | );
|
74 | }
|
75 | }
|
76 |
|
77 | if (__DEV__) {
|
78 | Router.propTypes = {
|
79 | children: PropTypes.node,
|
80 | history: PropTypes.object.isRequired,
|
81 | staticContext: PropTypes.object
|
82 | };
|
83 |
|
84 | Router.prototype.componentDidUpdate = function(prevProps) {
|
85 | warning(
|
86 | prevProps.history === this.props.history,
|
87 | "You cannot change <Router history>"
|
88 | );
|
89 | };
|
90 | }
|
91 |
|
92 | export default Router;
|