1 | import React from "react";
|
2 | import PropTypes from "prop-types";
|
3 | import { createLocation, locationsAreEqual } from "history";
|
4 | import invariant from "tiny-invariant";
|
5 |
|
6 | import Lifecycle from "./Lifecycle.js";
|
7 | import RouterContext from "./RouterContext.js";
|
8 | import generatePath from "./generatePath.js";
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | function Redirect({ computedMatch, to, push = false }) {
|
14 | return (
|
15 | <RouterContext.Consumer>
|
16 | {context => {
|
17 | invariant(context, "You should not use <Redirect> outside a <Router>");
|
18 |
|
19 | const { history, staticContext } = context;
|
20 |
|
21 | const method = push ? history.push : history.replace;
|
22 | const location = createLocation(
|
23 | computedMatch
|
24 | ? typeof to === "string"
|
25 | ? generatePath(to, computedMatch.params)
|
26 | : {
|
27 | ...to,
|
28 | pathname: generatePath(to.pathname, computedMatch.params)
|
29 | }
|
30 | : to
|
31 | );
|
32 |
|
33 |
|
34 |
|
35 | if (staticContext) {
|
36 | method(location);
|
37 | return null;
|
38 | }
|
39 |
|
40 | return (
|
41 | <Lifecycle
|
42 | onMount={() => {
|
43 | method(location);
|
44 | }}
|
45 | onUpdate={(self, prevProps) => {
|
46 | const prevLocation = createLocation(prevProps.to);
|
47 | if (
|
48 | !locationsAreEqual(prevLocation, {
|
49 | ...location,
|
50 | key: prevLocation.key
|
51 | })
|
52 | ) {
|
53 | method(location);
|
54 | }
|
55 | }}
|
56 | to={to}
|
57 | />
|
58 | );
|
59 | }}
|
60 | </RouterContext.Consumer>
|
61 | );
|
62 | }
|
63 |
|
64 | if (__DEV__) {
|
65 | Redirect.propTypes = {
|
66 | push: PropTypes.bool,
|
67 | from: PropTypes.string,
|
68 | to: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired
|
69 | };
|
70 | }
|
71 |
|
72 | export default Redirect;
|