1 |
3a515b92
|
cagy
|
import React from "react";
|
2 |
|
|
import PropTypes from "prop-types";
|
3 |
|
|
import invariant from "tiny-invariant";
|
4 |
|
|
import warning from "tiny-warning";
|
5 |
|
|
|
6 |
|
|
import RouterContext from "./RouterContext";
|
7 |
|
|
import matchPath from "./matchPath";
|
8 |
|
|
|
9 |
|
|
/**
|
10 |
|
|
* The public API for rendering the first <Route> that matches.
|
11 |
|
|
*/
|
12 |
|
|
class Switch extends React.Component {
|
13 |
|
|
render() {
|
14 |
|
|
return (
|
15 |
|
|
<RouterContext.Consumer>
|
16 |
|
|
{context => {
|
17 |
|
|
invariant(context, "You should not use <Switch> outside a <Router>");
|
18 |
|
|
|
19 |
|
|
const location = this.props.location || context.location;
|
20 |
|
|
|
21 |
|
|
let element, match;
|
22 |
|
|
|
23 |
|
|
// We use React.Children.forEach instead of React.Children.toArray().find()
|
24 |
|
|
// here because toArray adds keys to all child elements and we do not want
|
25 |
|
|
// to trigger an unmount/remount for two <Route>s that render the same
|
26 |
|
|
// component at different URLs.
|
27 |
|
|
React.Children.forEach(this.props.children, child => {
|
28 |
|
|
if (match == null && React.isValidElement(child)) {
|
29 |
|
|
element = child;
|
30 |
|
|
|
31 |
|
|
const path = child.props.path || child.props.from;
|
32 |
|
|
|
33 |
|
|
match = path
|
34 |
|
|
? matchPath(location.pathname, { ...child.props, path })
|
35 |
|
|
: context.match;
|
36 |
|
|
}
|
37 |
|
|
});
|
38 |
|
|
|
39 |
|
|
return match
|
40 |
|
|
? React.cloneElement(element, { location, computedMatch: match })
|
41 |
|
|
: null;
|
42 |
|
|
}}
|
43 |
|
|
</RouterContext.Consumer>
|
44 |
|
|
);
|
45 |
|
|
}
|
46 |
|
|
}
|
47 |
|
|
|
48 |
|
|
if (__DEV__) {
|
49 |
|
|
Switch.propTypes = {
|
50 |
|
|
children: PropTypes.node,
|
51 |
|
|
location: PropTypes.object
|
52 |
|
|
};
|
53 |
|
|
|
54 |
|
|
Switch.prototype.componentDidUpdate = function(prevProps) {
|
55 |
|
|
warning(
|
56 |
|
|
!(this.props.location && !prevProps.location),
|
57 |
|
|
'<Switch> elements should not change from uncontrolled to controlled (or vice versa). You initially used no "location" prop and then provided one on a subsequent render.'
|
58 |
|
|
);
|
59 |
|
|
|
60 |
|
|
warning(
|
61 |
|
|
!(!this.props.location && prevProps.location),
|
62 |
|
|
'<Switch> elements should not change from controlled to uncontrolled (or vice versa). You provided a "location" prop initially but omitted it on a subsequent render.'
|
63 |
|
|
);
|
64 |
|
|
};
|
65 |
|
|
}
|
66 |
|
|
|
67 |
|
|
export default Switch;
|