1 | 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.js";
|
7 | import matchPath from "./matchPath.js";
|
8 |
|
9 |
|
10 |
|
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 |
|
24 |
|
25 |
|
26 |
|
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;
|