Skip to content

Commit d38ebf3

Browse files
committed
Keep path-listening logic in separate mixin
1 parent 4aa3848 commit d38ebf3

File tree

2 files changed

+76
-54
lines changed

2 files changed

+76
-54
lines changed

modules/components/Routes.js

Lines changed: 5 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,8 @@ var canUseDOM = require('react/lib/ExecutionEnvironment').canUseDOM;
55
var Promise = require('when/lib/Promise');
66
var LocationActions = require('../actions/LocationActions');
77
var Route = require('../components/Route');
8-
var DefaultLocation = require('../locations/DefaultLocation');
9-
var HashLocation = require('../locations/HashLocation');
10-
var HistoryLocation = require('../locations/HistoryLocation');
11-
var RefreshLocation = require('../locations/RefreshLocation');
128
var ActiveDelegate = require('../mixins/ActiveDelegate');
13-
var PathStore = require('../stores/PathStore');
9+
var PathListener = require('../mixins/PathListener');
1410
var RouteStore = require('../stores/RouteStore');
1511
var Path = require('../utils/Path');
1612
var Redirect = require('../utils/Redirect');
@@ -21,15 +17,6 @@ var Transition = require('../utils/Transition');
2117
*/
2218
var REF_NAME = '__activeRoute__';
2319

24-
/**
25-
* A hash of { name, location } pairs of all locations.
26-
*/
27-
var NAMED_LOCATIONS = {
28-
hash: HashLocation,
29-
history: HistoryLocation,
30-
refresh: RefreshLocation
31-
};
32-
3320
/**
3421
* The default handler for aborted transitions. Redirects replace
3522
* the current URL and all others roll it back.
@@ -81,26 +68,19 @@ var Routes = React.createClass({
8168

8269
displayName: 'Routes',
8370

84-
mixins: [ ActiveDelegate ],
71+
mixins: [ ActiveDelegate, PathListener ],
8572

8673
propTypes: {
8774
onAbortedTransition: React.PropTypes.func.isRequired,
8875
onTransitionError: React.PropTypes.func.isRequired,
89-
preserveScrollPosition: React.PropTypes.bool,
90-
location: function (props, propName, componentName) {
91-
var location = props[propName];
92-
93-
if (typeof location === 'string' && !(location in NAMED_LOCATIONS))
94-
return new Error('Unknown location "' + location + '", see ' + componentName);
95-
}
76+
preserveScrollPosition: React.PropTypes.bool
9677
},
9778

9879
getDefaultProps: function () {
9980
return {
10081
onAbortedTransition: defaultAbortedTransitionHandler,
10182
onTransitionError: defaultTransitionErrorHandler,
102-
preserveScrollPosition: false,
103-
location: DefaultLocation
83+
preserveScrollPosition: false
10484
};
10585
},
10686

@@ -110,35 +90,6 @@ var Routes = React.createClass({
11090
};
11191
},
11292

113-
componentWillMount: function () {
114-
PathStore.setup(this.getLocation());
115-
},
116-
117-
componentDidMount: function () {
118-
PathStore.addChangeListener(this.handlePathChange);
119-
this.handlePathChange();
120-
},
121-
122-
componentWillUnmount: function () {
123-
PathStore.removeChangeListener(this.handlePathChange);
124-
},
125-
126-
handlePathChange: function () {
127-
this.transitionTo(PathStore.getCurrentPath());
128-
},
129-
130-
/**
131-
* Gets the location object this component uses to watch for URL changes.
132-
*/
133-
getLocation: function () {
134-
var location = this.props.location;
135-
136-
if (typeof location === 'string')
137-
return NAMED_LOCATIONS[location];
138-
139-
return location;
140-
},
141-
14293
/**
14394
* Gets the <Route> component that is currently active.
14495
*/
@@ -188,7 +139,7 @@ var Routes = React.createClass({
188139
* If you want to keep the URL in sync with transitions, use Router.transitionTo,
189140
* Router.replaceWith, or Router.goBack instead.
190141
*/
191-
transitionTo: function (path) {
142+
updatePath: function (path) {
192143
var routes = this;
193144
var transition = new Transition(path);
194145

modules/mixins/PathListener.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
var React = require('react');
2+
var DefaultLocation = require('../locations/DefaultLocation');
3+
var HashLocation = require('../locations/HashLocation');
4+
var HistoryLocation = require('../locations/HistoryLocation');
5+
var RefreshLocation = require('../locations/RefreshLocation');
6+
var PathStore = require('../stores/PathStore');
7+
8+
/**
9+
* A hash of { name, location } pairs.
10+
*/
11+
var NAMED_LOCATIONS = {
12+
hash: HashLocation,
13+
history: HistoryLocation,
14+
refresh: RefreshLocation
15+
};
16+
17+
/**
18+
* A mixin for components that listen for changes to the current
19+
* URL path.
20+
*/
21+
var PathListener = {
22+
23+
propTypes: {
24+
location: function (props, propName, componentName) {
25+
var location = props[propName];
26+
27+
if (typeof location === 'string' && !(location in NAMED_LOCATIONS))
28+
return new Error('Unknown location "' + location + '", see ' + componentName);
29+
}
30+
},
31+
32+
getDefaultProps: function () {
33+
return {
34+
location: DefaultLocation
35+
};
36+
},
37+
38+
/**
39+
* Gets the location object this component uses to watch for
40+
* changes to the current URL path.
41+
*/
42+
getLocation: function () {
43+
var location = this.props.location;
44+
45+
if (typeof location === 'string')
46+
return NAMED_LOCATIONS[location];
47+
48+
return location;
49+
},
50+
51+
componentWillMount: function () {
52+
PathStore.setup(this.getLocation());
53+
},
54+
55+
componentDidMount: function () {
56+
PathStore.addChangeListener(this.handlePathChange);
57+
this.handlePathChange();
58+
},
59+
60+
componentWillUnmount: function () {
61+
PathStore.removeChangeListener(this.handlePathChange);
62+
},
63+
64+
handlePathChange: function () {
65+
if (this.isMounted() && this.updatePath)
66+
this.updatePath(PathStore.getCurrentPath());
67+
}
68+
69+
};
70+
71+
module.exports = PathListener;

0 commit comments

Comments
 (0)