Projekt

Obecné

Profil

Stáhnout (4.32 KB) Statistiky
| Větev: | Revize:
1
import React from "react";
2
import { isValidElementType } from "react-is";
3
import PropTypes from "prop-types";
4
import invariant from "tiny-invariant";
5
import warning from "tiny-warning";
6

    
7
import RouterContext from "./RouterContext";
8
import matchPath from "./matchPath";
9

    
10
function isEmptyChildren(children) {
11
  return React.Children.count(children) === 0;
12
}
13

    
14
function evalChildrenDev(children, props, path) {
15
  const value = children(props);
16

    
17
  warning(
18
    value !== undefined,
19
    "You returned `undefined` from the `children` function of " +
20
      `<Route${path ? ` path="${path}"` : ""}>, but you ` +
21
      "should have returned a React element or `null`"
22
  );
23

    
24
  return value || null;
25
}
26

    
27
/**
28
 * The public API for matching a single path and rendering.
29
 */
30
class Route extends React.Component {
31
  render() {
32
    return (
33
      <RouterContext.Consumer>
34
        {context => {
35
          invariant(context, "You should not use <Route> outside a <Router>");
36

    
37
          const location = this.props.location || context.location;
38
          const match = this.props.computedMatch
39
            ? this.props.computedMatch // <Switch> already computed the match for us
40
            : this.props.path
41
            ? matchPath(location.pathname, this.props)
42
            : context.match;
43

    
44
          const props = { ...context, location, match };
45

    
46
          let { children, component, render } = this.props;
47

    
48
          // Preact uses an empty array as children by
49
          // default, so use null if that's the case.
50
          if (Array.isArray(children) && children.length === 0) {
51
            children = null;
52
          }
53

    
54
          return (
55
            <RouterContext.Provider value={props}>
56
              {props.match
57
                ? children
58
                  ? typeof children === "function"
59
                    ? __DEV__
60
                      ? evalChildrenDev(children, props, this.props.path)
61
                      : children(props)
62
                    : children
63
                  : component
64
                  ? React.createElement(component, props)
65
                  : render
66
                  ? render(props)
67
                  : null
68
                : typeof children === "function"
69
                ? __DEV__
70
                  ? evalChildrenDev(children, props, this.props.path)
71
                  : children(props)
72
                : null}
73
            </RouterContext.Provider>
74
          );
75
        }}
76
      </RouterContext.Consumer>
77
    );
78
  }
79
}
80

    
81
if (__DEV__) {
82
  Route.propTypes = {
83
    children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
84
    component: (props, propName) => {
85
      if (props[propName] && !isValidElementType(props[propName])) {
86
        return new Error(
87
          `Invalid prop 'component' supplied to 'Route': the prop is not a valid React component`
88
        );
89
      }
90
    },
91
    exact: PropTypes.bool,
92
    location: PropTypes.object,
93
    path: PropTypes.oneOfType([
94
      PropTypes.string,
95
      PropTypes.arrayOf(PropTypes.string)
96
    ]),
97
    render: PropTypes.func,
98
    sensitive: PropTypes.bool,
99
    strict: PropTypes.bool
100
  };
101

    
102
  Route.prototype.componentDidMount = function() {
103
    warning(
104
      !(
105
        this.props.children &&
106
        !isEmptyChildren(this.props.children) &&
107
        this.props.component
108
      ),
109
      "You should not use <Route component> and <Route children> in the same route; <Route component> will be ignored"
110
    );
111

    
112
    warning(
113
      !(
114
        this.props.children &&
115
        !isEmptyChildren(this.props.children) &&
116
        this.props.render
117
      ),
118
      "You should not use <Route render> and <Route children> in the same route; <Route render> will be ignored"
119
    );
120

    
121
    warning(
122
      !(this.props.component && this.props.render),
123
      "You should not use <Route component> and <Route render> in the same route; <Route render> will be ignored"
124
    );
125
  };
126

    
127
  Route.prototype.componentDidUpdate = function(prevProps) {
128
    warning(
129
      !(this.props.location && !prevProps.location),
130
      '<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.'
131
    );
132

    
133
    warning(
134
      !(!this.props.location && prevProps.location),
135
      '<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.'
136
    );
137
  };
138
}
139

    
140
export default Route;
(5-5/14)