Switch.js 2.1 KB

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