1 | import React from "react";
|
2 | import PropTypes from "prop-types";
|
3 | import { createLocation, createPath } from "history";
|
4 | import invariant from "tiny-invariant";
|
5 | import warning from "tiny-warning";
|
6 |
|
7 | import Router from "./Router.js";
|
8 |
|
9 | function addLeadingSlash(path) {
|
10 | return path.charAt(0) === "/" ? path : "/" + path;
|
11 | }
|
12 |
|
13 | function addBasename(basename, location) {
|
14 | if (!basename) return location;
|
15 |
|
16 | return {
|
17 | ...location,
|
18 | pathname: addLeadingSlash(basename) + location.pathname
|
19 | };
|
20 | }
|
21 |
|
22 | function stripBasename(basename, location) {
|
23 | if (!basename) return location;
|
24 |
|
25 | const base = addLeadingSlash(basename);
|
26 |
|
27 | if (location.pathname.indexOf(base) !== 0) return location;
|
28 |
|
29 | return {
|
30 | ...location,
|
31 | pathname: location.pathname.substr(base.length)
|
32 | };
|
33 | }
|
34 |
|
35 | function createURL(location) {
|
36 | return typeof location === "string" ? location : createPath(location);
|
37 | }
|
38 |
|
39 | function staticHandler(methodName) {
|
40 | return () => {
|
41 | invariant(false, "You cannot %s with <StaticRouter>", methodName);
|
42 | };
|
43 | }
|
44 |
|
45 | function noop() {}
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 | class StaticRouter extends React.Component {
|
54 | navigateTo(location, action) {
|
55 | const { basename = "", context = {} } = this.props;
|
56 | context.action = action;
|
57 | context.location = addBasename(basename, createLocation(location));
|
58 | context.url = createURL(context.location);
|
59 | }
|
60 |
|
61 | handlePush = location => this.navigateTo(location, "PUSH");
|
62 | handleReplace = location => this.navigateTo(location, "REPLACE");
|
63 | handleListen = () => noop;
|
64 | handleBlock = () => noop;
|
65 |
|
66 | render() {
|
67 | const { basename = "", context = {}, location = "/", ...rest } = this.props;
|
68 |
|
69 | const history = {
|
70 | createHref: path => addLeadingSlash(basename + createURL(path)),
|
71 | action: "POP",
|
72 | location: stripBasename(basename, createLocation(location)),
|
73 | push: this.handlePush,
|
74 | replace: this.handleReplace,
|
75 | go: staticHandler("go"),
|
76 | goBack: staticHandler("goBack"),
|
77 | goForward: staticHandler("goForward"),
|
78 | listen: this.handleListen,
|
79 | block: this.handleBlock
|
80 | };
|
81 |
|
82 | return <Router {...rest} history={history} staticContext={context} />;
|
83 | }
|
84 | }
|
85 |
|
86 | if (__DEV__) {
|
87 | StaticRouter.propTypes = {
|
88 | basename: PropTypes.string,
|
89 | context: PropTypes.object,
|
90 | location: PropTypes.oneOfType([PropTypes.string, PropTypes.object])
|
91 | };
|
92 |
|
93 | StaticRouter.prototype.componentDidMount = function() {
|
94 | warning(
|
95 | !this.props.history,
|
96 | "<StaticRouter> ignores the history prop. To use a custom history, " +
|
97 | "use `import { Router }` instead of `import { StaticRouter as Router }`."
|
98 | );
|
99 | };
|
100 | }
|
101 |
|
102 | export default StaticRouter;
|