123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- import React from "react";
- import { isValidElementType } from "react-is";
- import PropTypes from "prop-types";
- import invariant from "tiny-invariant";
- import warning from "tiny-warning";
- import RouterContext from "./RouterContext.js";
- import matchPath from "./matchPath.js";
- function isEmptyChildren(children) {
- return React.Children.count(children) === 0;
- }
- function evalChildrenDev(children, props, path) {
- const value = children(props);
- warning(
- value !== undefined,
- "You returned `undefined` from the `children` function of " +
- `<Route${path ? ` path="${path}"` : ""}>, but you ` +
- "should have returned a React element or `null`"
- );
- return value || null;
- }
- /**
- * The public API for matching a single path and rendering.
- */
- class Route extends React.Component {
- render() {
- return (
- <RouterContext.Consumer>
- {context => {
- invariant(context, "You should not use <Route> outside a <Router>");
- const location = this.props.location || context.location;
- const match = this.props.computedMatch
- ? this.props.computedMatch // <Switch> already computed the match for us
- : this.props.path
- ? matchPath(location.pathname, this.props)
- : context.match;
- const props = { ...context, location, match };
- let { children, component, render } = this.props;
- // Preact uses an empty array as children by
- // default, so use null if that's the case.
- if (Array.isArray(children) && isEmptyChildren(children)) {
- children = null;
- }
- return (
- <RouterContext.Provider value={props}>
- {props.match
- ? children
- ? typeof children === "function"
- ? __DEV__
- ? evalChildrenDev(children, props, this.props.path)
- : children(props)
- : children
- : component
- ? React.createElement(component, props)
- : render
- ? render(props)
- : null
- : typeof children === "function"
- ? __DEV__
- ? evalChildrenDev(children, props, this.props.path)
- : children(props)
- : null}
- </RouterContext.Provider>
- );
- }}
- </RouterContext.Consumer>
- );
- }
- }
- if (__DEV__) {
- Route.propTypes = {
- children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
- component: (props, propName) => {
- if (props[propName] && !isValidElementType(props[propName])) {
- return new Error(
- `Invalid prop 'component' supplied to 'Route': the prop is not a valid React component`
- );
- }
- },
- exact: PropTypes.bool,
- location: PropTypes.object,
- path: PropTypes.oneOfType([
- PropTypes.string,
- PropTypes.arrayOf(PropTypes.string)
- ]),
- render: PropTypes.func,
- sensitive: PropTypes.bool,
- strict: PropTypes.bool
- };
- Route.prototype.componentDidMount = function() {
- warning(
- !(
- this.props.children &&
- !isEmptyChildren(this.props.children) &&
- this.props.component
- ),
- "You should not use <Route component> and <Route children> in the same route; <Route component> will be ignored"
- );
- warning(
- !(
- this.props.children &&
- !isEmptyChildren(this.props.children) &&
- this.props.render
- ),
- "You should not use <Route render> and <Route children> in the same route; <Route render> will be ignored"
- );
- warning(
- !(this.props.component && this.props.render),
- "You should not use <Route component> and <Route render> in the same route; <Route render> will be ignored"
- );
- };
- Route.prototype.componentDidUpdate = function(prevProps) {
- warning(
- !(this.props.location && !prevProps.location),
- '<Route> 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.'
- );
- warning(
- !(!this.props.location && prevProps.location),
- '<Route> elements should not change from controlled to uncontrolled (or vice versa). You provided a "location" prop initially but omitted it on a subsequent render.'
- );
- };
- }
- export default Route;
|