diff --git a/examples/pinterest/app.css b/examples/pinterest/app.css
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/examples/pinterest/app.js b/examples/pinterest/app.js
index 7cbaf25051..476f443573 100644
--- a/examples/pinterest/app.js
+++ b/examples/pinterest/app.js
@@ -45,7 +45,7 @@ var Feed = React.createClass({
{pictures.map(picture => (

@@ -116,7 +116,7 @@ var RootRoute = {
}
};
-React.render(
, document.getElementById('example'));
+React.render(, document.getElementById('example'));
// Wait a sec ... what's happening?
//
diff --git a/modules/BrowserHistory.js b/modules/BrowserHistory.js
index 7d13eaff55..94984609fd 100644
--- a/modules/BrowserHistory.js
+++ b/modules/BrowserHistory.js
@@ -78,13 +78,15 @@ export class BrowserHistory extends DOMHistory {
}
// http://www.w3.org/TR/2011/WD-html5-20110113/history.html#dom-history-pushstate
- push(path) {
+ push(path, transitionState) {
if (this.isSupported) {
this._recordScrollPosition();
var key = createRandomKey();
window.history.pushState({ key }, '', path);
- this.location = this._createLocation(path, key, NavigationTypes.PUSH);
+ this.location = this._createLocation(
+ path, key, NavigationTypes.PUSH, transitionState
+ );
this._notifyChange();
} else {
window.location = path;
@@ -92,11 +94,13 @@ export class BrowserHistory extends DOMHistory {
}
// http://www.w3.org/TR/2011/WD-html5-20110113/history.html#dom-history-replacestate
- replace(path) {
+ replace(path, transitionState) {
if (this.isSupported) {
var key = createRandomKey();
window.history.replaceState({ key }, '', path);
- this.location = this._createLocation(path, key, NavigationTypes.REPLACE);
+ this.location = this._createLocation(
+ path, key, NavigationTypes.REPLACE, transitionState
+ );
this._notifyChange();
} else {
window.location.replace(path);
diff --git a/modules/DOMHistory.js b/modules/DOMHistory.js
index 35ad09e48e..7df20724c8 100644
--- a/modules/DOMHistory.js
+++ b/modules/DOMHistory.js
@@ -11,6 +11,7 @@ export class DOMHistory extends History {
super();
this.getScrollPosition = getScrollPosition;
this.scrollHistory = {};
+ this.stateHistory = {};
}
go(n) {
@@ -20,11 +21,13 @@ export class DOMHistory extends History {
window.history.go(n);
}
- _createLocation(path, key, navigationType) {
+ _createLocation(path, key, navigationType, transitionState) {
var scrollKey = key || path;
var scrollPosition = this.scrollHistory[scrollKey];
+ transitionState = transitionState || this.stateHistory[key];
+ this.stateHistory[key] = transitionState;
- return new Location(path, key, navigationType, scrollPosition);
+ return new Location(path, key, navigationType, scrollPosition, transitionState);
}
_recordScrollPosition() {
diff --git a/modules/Link.js b/modules/Link.js
index 3db61d4cad..540d997df3 100644
--- a/modules/Link.js
+++ b/modules/Link.js
@@ -1,4 +1,5 @@
import React from 'react';
+console.log('got the source');
var { object, string, func } = React.PropTypes;
@@ -69,7 +70,9 @@ export class Link extends React.Component {
event.preventDefault();
if (allowTransition)
- this.context.router.transitionTo(this.props.to, this.props.query);
+ this.context.router.transitionTo(
+ this.props.to, this.props.query, this.props.transitionState
+ );
}
render() {
diff --git a/modules/Location.js b/modules/Location.js
index da7703b36f..6b98d93cea 100644
--- a/modules/Location.js
+++ b/modules/Location.js
@@ -20,16 +20,17 @@ export class Location {
return new Location(object);
if (object && object.path)
- return new Location(object.path, object.key, object.navigationType, object.scrollPosition);
+ return new Location(object.path, object.key, object.navigationType, object.scrollPosition, object.transitionState);
throw new Error('Unable to create a Location from ' + object);
}
- constructor(path, key=null, navigationType=NavigationTypes.POP, scrollPosition=null) {
+ constructor(path, key=null, navigationType=NavigationTypes.POP, scrollPosition=null, transitionState=null) {
this.path = path;
this.key = key;
this.navigationType = navigationType;
this.scrollPosition = scrollPosition;
+ this.transitionState = transitionState;
}
}
diff --git a/modules/MemoryHistory.js b/modules/MemoryHistory.js
index 0e8b51e4ca..c209769190 100644
--- a/modules/MemoryHistory.js
+++ b/modules/MemoryHistory.js
@@ -35,17 +35,17 @@ export class MemoryHistory extends History {
}
// http://www.w3.org/TR/2011/WD-html5-20110113/history.html#dom-history-pushstate
- push(path) {
+ push(path, transitionState) {
this.current += 1;
this.entries = this.entries.slice(0, this.current).concat([ path ]);
- this.location = new Location(path, null, NavigationTypes.PUSH);
+ this.location = new Location(path, null, NavigationTypes.PUSH, null, transitionState);
this._notifyChange();
}
// http://www.w3.org/TR/2011/WD-html5-20110113/history.html#dom-history-replacestate
- replace(path) {
+ replace(path, transitionState) {
this.entries[this.current] = path;
- this.location = new Location(path, null, NavigationTypes.REPLACE);
+ this.location = new Location(path, null, NavigationTypes.REPLACE, null, transitionState);
this._notifyChange();
}
diff --git a/modules/Router.js b/modules/Router.js
index a4abebc799..b4b9b08254 100644
--- a/modules/Router.js
+++ b/modules/Router.js
@@ -146,7 +146,7 @@ export class Router extends React.Component {
try {
for (var i = 0, len = hooks.length; i < len; ++i) {
- hooks[i].call(this);
+ hooks[i].call(this, location.transitionState);
if (this.nextLocation !== nextLocation)
break; // No need to proceed further.
@@ -218,29 +218,29 @@ export class Router extends React.Component {
return path;
}
- transitionTo(pathname, query) {
+ transitionTo(pathname, query, transitionState) {
var path = this.makePath(pathname, query);
var { history } = this.props;
if (history) {
if (this.nextLocation) {
- history.replace(path);
+ history.replace(path, transitionState);
} else {
- history.push(path);
+ history.push(path, transitionState);
}
} else {
- this._updateLocation(path);
+ this._updateLocation({ path, transitionState });
}
}
- replaceWith(pathname, query) {
+ replaceWith(pathname, query, transitionState) {
var path = this.makePath(pathname, query);
var { history } = this.props;
if (history) {
- history.replace(path);
+ history.replace(path, transitionState);
} else {
- this._updateLocation(path);
+ this._updateLocation({path, transitionState});
}
}
diff --git a/modules/__tests__/getProps-test.js b/modules/__tests__/getProps-test.js
index f044e4996a..54bfb5ba4f 100644
--- a/modules/__tests__/getProps-test.js
+++ b/modules/__tests__/getProps-test.js
@@ -1,4 +1,5 @@
import expect, { spyOn } from 'expect';
+import Location from '../Location';
import { getProps } from '../getProps';
import qs from 'qs';
@@ -17,7 +18,7 @@ describe('Matching pathnames', function () {
CoursesRoute = {
path: 'courses',
- getChildRoutes(callback) {
+ getChildRoutes(transitionState, callback) {
callback(null, [ GradesRoute ]);
}
};
@@ -35,7 +36,7 @@ describe('Matching pathnames', function () {
};
CourseRoute = {
- getChildRoutes(callback) {
+ getChildRoutes(transitionState, callback) {
setTimeout(function () {
callback(null, [ CourseGradesRoute, AssignmentRoute, AssignmentsRoute ]);
}, 0);
@@ -53,7 +54,7 @@ describe('Matching pathnames', function () {
ProfileRoute = {
path: 'profile',
- getIndexRoute (cb) {
+ getIndexRoute (transitionState, cb) {
cb(null, ProfileIndexRoute);
}
};
@@ -210,6 +211,46 @@ describe('Matching pathnames', function () {
expect(outerProps).toNotExist();
});
});
+
+});
+
+describe('transitionState', function () {
+ var RouteA = {path: 'test'};
+ var RouteB = {path: 'test'};
+ var RootRoute = {
+ path: '/',
+ getIndexRoute (transitionState, cb) {
+ if (transitionState.test)
+ cb(null, RouteA);
+ else
+ cb(null, RouteB);
+ },
+ getChildRoutes (transitionState, cb) {
+ if (transitionState.test)
+ cb(null, [RouteA]);
+ else
+ cb(null, [RouteB]);
+ }
+ };
+
+ it('is passed to getChildRoutes', function (done) {
+ var transitionState = { test: true };
+ var location = new Location('/test', null, null, null, transitionState);
+ getProps(RootRoute, location, parseQueryString, function (err, props) {
+ expect(props.branch).toEqual([RootRoute, RouteA]);
+ done();
+ });
+ });
+
+ it('is passed to getIndexRoute', function (done) {
+ var transitionState = { test: true };
+ var location = new Location('/', null, null, null, transitionState);
+ getProps(RootRoute, location, parseQueryString, function (err, props) {
+ expect(props.branch).toEqual([RootRoute, RouteA]);
+ done();
+ });
+ });
+
});
describe('Matching params', function () {
@@ -364,4 +405,5 @@ describe('Matching params', function () {
});
});
});
+
});
diff --git a/modules/getProps.js b/modules/getProps.js
index 6339d0e3fb..97d39d6916 100644
--- a/modules/getProps.js
+++ b/modules/getProps.js
@@ -3,11 +3,11 @@ import { createRoutes } from './RouteUtils';
import { getPathname, getQueryString, matchPattern, stripLeadingSlashes } from './PathUtils';
import Location from './Location';
-function getChildRoutes(route, callback) {
+function getChildRoutes(route, transitionState, callback) {
if (route.childRoutes) {
callback(null, route.childRoutes);
} else if (route.getChildRoutes) {
- route.getChildRoutes(callback);
+ route.getChildRoutes(transitionState, callback);
} else {
callback();
}
@@ -33,7 +33,7 @@ function createParams(paramNames, paramValues) {
return assignParams({}, paramNames, paramValues);
}
-function matchRouteDeep(route, pathname, callback) {
+function matchRouteDeep(route, pathname, transitionState, callback) {
var { remainingPathname, paramNames, paramValues } = matchPattern(route.path, pathname);
var isExactMatch = remainingPathname === '';
@@ -45,7 +45,7 @@ function matchRouteDeep(route, pathname, callback) {
branch.push(route.indexRoute);
callback(null, { params, branch });
} else if (route.getIndexRoute) {
- route.getIndexRoute(function (error, indexRoute) {
+ route.getIndexRoute(transitionState, function (error, indexRoute) {
if (error) {
callback(error);
} else {
@@ -58,12 +58,12 @@ function matchRouteDeep(route, pathname, callback) {
}
} else if (remainingPathname != null) {
// This route matched at least some of the path.
- getChildRoutes(route, function (error, childRoutes) {
+ getChildRoutes(route, transitionState, function (error, childRoutes) {
if (error) {
callback(error);
} else if (childRoutes) {
// Check the child routes to see if any of them match.
- matchRoutes(childRoutes, remainingPathname, function (error, match) {
+ matchRoutes(childRoutes, remainingPathname, transitionState, function (error, match) {
if (error) {
callback(error);
} else if (match) {
@@ -84,11 +84,11 @@ function matchRouteDeep(route, pathname, callback) {
}
}
-function matchRoutes(routes, pathname, callback) {
+function matchRoutes(routes, pathname, transitionState, callback) {
routes = createRoutes(routes);
loopAsync(routes.length, function (index, next, done) {
- matchRouteDeep(routes[index], pathname, function (error, match) {
+ matchRouteDeep(routes[index], pathname, transitionState, function (error, match) {
if (error || match) {
done(error, match);
} else {
@@ -116,7 +116,7 @@ export function getProps(routes, location, parseQueryString, callback) {
var pathname = stripLeadingSlashes(getPathname(location.path));
- matchRoutes(routes, pathname, function (error, props) {
+ matchRoutes(routes, pathname, location.transitionState, function (error, props) {
if (error || props == null) {
callback(error);
} else {