|
1 | 1 | import React, { PropTypes } from 'react'
|
2 | 2 | import { stringify, parse as parseQueryString } from 'query-string'
|
3 |
| -import { createRouterLocation, createRouterPath } from './LocationUtils' |
4 | 3 | import MatchProvider from './MatchProvider'
|
| 4 | +import { |
| 5 | + locationsAreEqual, |
| 6 | + createRouterLocation, |
| 7 | + createRouterPath |
| 8 | +} from './LocationUtils' |
5 | 9 | import {
|
6 | 10 | action as actionType,
|
7 | 11 | location as locationType,
|
@@ -31,61 +35,83 @@ class StaticRouter extends React.Component {
|
31 | 35 | }
|
32 | 36 |
|
33 | 37 | static defaultProps = {
|
34 |
| - createHref: path => path, |
35 | 38 | stringifyQuery,
|
36 |
| - parseQueryString |
| 39 | + parseQueryString, |
| 40 | + createHref: path => path |
37 | 41 | }
|
38 | 42 |
|
39 | 43 | static childContextTypes = {
|
40 | 44 | router: routerContextType.isRequired,
|
41 | 45 | location: locationType.isRequired // TODO: Remove location state from context
|
42 | 46 | }
|
43 | 47 |
|
44 |
| - createLocationForContext(loc) { |
| 48 | + createLocation(location) { |
45 | 49 | const { parseQueryString, stringifyQuery } = this.props
|
46 |
| - return createRouterLocation(loc, parseQueryString, stringifyQuery) |
| 50 | + return createRouterLocation(location, parseQueryString, stringifyQuery) |
47 | 51 | }
|
48 | 52 |
|
49 |
| - getChildContext() { |
50 |
| - const createHref = (to) => { |
51 |
| - let path = createRouterPath(to, this.props.stringifyQuery) |
52 |
| - if (this.props.basename) path = this.props.basename + path |
53 |
| - return this.props.createHref(path) |
54 |
| - } |
| 53 | + transitionTo = (location) => { |
| 54 | + this.props.onPush(this.createLocation(location)) |
| 55 | + } |
| 56 | + |
| 57 | + replaceWith = (location) => { |
| 58 | + this.props.onReplace(this.createLocation(location)) |
| 59 | + } |
| 60 | + |
| 61 | + blockTransitions = (prompt) => { |
| 62 | + this.props.blockTransitions(prompt) |
| 63 | + } |
55 | 64 |
|
56 |
| - const location = this.getLocation() |
| 65 | + createHref = (to) => { |
| 66 | + let path = createRouterPath(to, this.props.stringifyQuery) |
| 67 | + |
| 68 | + if (this.props.basename) |
| 69 | + path = this.props.basename + path |
| 70 | + |
| 71 | + return this.props.createHref(path) |
| 72 | + } |
57 | 73 |
|
| 74 | + getRouterContext() { |
58 | 75 | return {
|
59 |
| - location, |
60 |
| - router: { |
61 |
| - createHref, |
62 |
| - transitionTo: (loc) => { |
63 |
| - this.props.onPush(this.createLocationForContext(loc)) |
64 |
| - }, |
65 |
| - replaceWith: (loc) => { |
66 |
| - this.props.onReplace(this.createLocationForContext(loc)) |
67 |
| - }, |
68 |
| - blockTransitions: (getPromptMessage) => { |
69 |
| - this.props.blockTransitions(getPromptMessage) |
70 |
| - } |
71 |
| - } |
| 76 | + transitionTo: this.transitionTo, |
| 77 | + replaceWith: this.replaceWith, |
| 78 | + blockTransitions: this.blockTransitions, |
| 79 | + createHref: this.createHref |
72 | 80 | }
|
73 | 81 | }
|
74 | 82 |
|
75 |
| - getLocation() { |
76 |
| - // TODO: maybe memoize this on willReceiveProps to get extreme w/ perf |
77 |
| - const { location, parseQueryString, stringifyQuery } = this.props |
78 |
| - return createRouterLocation(location, parseQueryString, stringifyQuery) |
| 83 | + getChildContext() { |
| 84 | + return { |
| 85 | + location: this.state.location, // TODO: Remove location state from context |
| 86 | + router: this.getRouterContext() |
| 87 | + } |
| 88 | + } |
| 89 | + |
| 90 | + state = { |
| 91 | + location: null |
| 92 | + } |
| 93 | + |
| 94 | + componentWillMount() { |
| 95 | + this.setState({ |
| 96 | + location: this.createLocation(this.props.location) |
| 97 | + }) |
| 98 | + } |
| 99 | + |
| 100 | + componentWillReceiveProps(nextProps) { |
| 101 | + const nextLocation = this.createLocation(nextProps.location) |
| 102 | + |
| 103 | + if (!locationsAreEqual(this.state.location, nextLocation)) |
| 104 | + this.setState({ location: nextLocation }) |
79 | 105 | }
|
80 | 106 |
|
81 | 107 | render() {
|
| 108 | + const { location } = this.state |
82 | 109 | const { children } = this.props
|
83 |
| - const location = this.getLocation() |
84 | 110 |
|
85 | 111 | return (
|
86 | 112 | <MatchProvider>
|
87 | 113 | {typeof children === 'function' ? (
|
88 |
| - children({ location, router: this.getChildContext().router }) |
| 114 | + children({ location, router: this.getRouterContext() }) |
89 | 115 | ) : (
|
90 | 116 | React.Children.only(children)
|
91 | 117 | )}
|
|
0 commit comments