@@ -70,54 +70,6 @@ function hasMatch(matches, match) {
70
70
} ) ;
71
71
}
72
72
73
- /**
74
- * Computes the next state for the given component and calls
75
- * callback(error, nextState) when finished. Also runs all
76
- * transition hooks along the way.
77
- */
78
- function computeNextState ( currentMatches , nextMatches , transition , callback ) {
79
- var fromMatches , toMatches ;
80
- if ( currentMatches . length ) {
81
- fromMatches = currentMatches . filter ( function ( match ) {
82
- return ! hasMatch ( nextMatches , match ) ;
83
- } ) ;
84
-
85
- toMatches = nextMatches . filter ( function ( match ) {
86
- return ! hasMatch ( currentMatches , match ) ;
87
- } ) ;
88
- } else {
89
- fromMatches = [ ] ;
90
- toMatches = nextMatches ;
91
- }
92
-
93
- var query = Path . extractQuery ( transition . path ) || { } ;
94
-
95
- runTransitionFromHooks ( fromMatches , transition , function ( error ) {
96
- if ( error || transition . isAborted )
97
- return callback ( error ) ;
98
-
99
- runTransitionToHooks ( toMatches , transition , query , function ( error ) {
100
- if ( error || transition . isAborted )
101
- return callback ( error ) ;
102
-
103
- var matches = currentMatches . slice ( 0 , currentMatches . length - fromMatches . length ) . concat ( toMatches ) ;
104
- var rootMatch = getRootMatch ( matches ) ;
105
- var params = ( rootMatch && rootMatch . params ) || { } ;
106
- var routes = matches . map ( function ( match ) {
107
- return match . route ;
108
- } ) ;
109
-
110
- callback ( null , {
111
- path : transition . path ,
112
- matches : matches ,
113
- activeRoutes : routes ,
114
- activeParams : params ,
115
- activeQuery : query
116
- } ) ;
117
- } ) ;
118
- } ) ;
119
- }
120
-
121
73
/**
122
74
* Calls the willTransitionFrom hook of all handlers in the given matches
123
75
* serially in reverse with the transition object and the current instance of
@@ -206,43 +158,6 @@ function returnNull() {
206
158
return null ;
207
159
}
208
160
209
- function computeHandlerProps ( matches , query ) {
210
- var handler = returnNull ;
211
- var props = {
212
- ref : null ,
213
- params : null ,
214
- query : null ,
215
- activeRouteHandler : handler ,
216
- key : null
217
- } ;
218
-
219
- reversedArray ( matches ) . forEach ( function ( match ) {
220
- var route = match . route ;
221
-
222
- props = Route . getUnreservedProps ( route . props ) ;
223
-
224
- props . ref = '__activeRoute__' ;
225
- props . params = match . params ;
226
- props . query = query ;
227
- props . activeRouteHandler = handler ;
228
-
229
- // TODO: Can we remove addHandlerKey?
230
- if ( route . props . addHandlerKey )
231
- props . key = Path . injectParams ( route . props . path , match . params ) ;
232
-
233
- handler = function ( props , addedProps ) {
234
- if ( arguments . length > 2 && typeof arguments [ 2 ] !== 'undefined' )
235
- throw new Error ( 'Passing children to a route handler is not supported' ) ;
236
-
237
- return route . props . handler (
238
- copyProperties ( props , addedProps )
239
- ) ;
240
- } . bind ( this , props ) ;
241
- } ) ;
242
-
243
- return props ;
244
- }
245
-
246
161
var ActiveContext = require ( '../mixins/ActiveContext' ) ;
247
162
var LocationContext = require ( '../mixins/LocationContext' ) ;
248
163
var RouteContext = require ( '../mixins/RouteContext' ) ;
@@ -312,59 +227,126 @@ var Routes = React.createClass({
312
227
} else if ( abortReason ) {
313
228
this . goBack ( ) ;
314
229
} else {
315
- updateMatchComponents ( this . state . matches , this . refs ) ;
230
+ this . setState ( nextState , function ( ) {
231
+ updateMatchComponents ( this . state . matches , this . refs ) ;
316
232
317
- this . updateScroll ( path , actionType ) ;
233
+ this . updateScroll ( path , actionType ) ;
318
234
319
- if ( this . props . onChange )
320
- this . props . onChange . call ( this ) ;
235
+ if ( this . props . onChange )
236
+ this . props . onChange . call ( this ) ;
237
+ } . bind ( this ) ) ;
321
238
}
322
239
} . bind ( this ) ) ;
323
240
} ,
324
241
325
242
/**
326
- * Performs a transition to the given path and calls callback(error, abortReason)
327
- * when the transition is finished and the component's state has been updated. If
328
- * there was an error, the first argument will not be null. Otherwise, if the
329
- * transition was aborted for some reason, it will be given in the second arg.
243
+ * Performs a transition to the given path and calls callback(error, abortReason, nextState)
244
+ * when the transition is finished. If there was an error, the first argument will not be null.
245
+ * Otherwise, if the transition was aborted for some reason, it will be given in the second arg.
330
246
*
331
- * In a transition, the router first determines which routes are involved by
332
- * beginning with the current route, up the route tree to the first parent route
333
- * that is shared with the destination route, and back down the tree to the
334
- * destination route. The willTransitionFrom hook is invoked on all route handlers
335
- * we're transitioning away from, in reverse nesting order. Likewise, the
247
+ * In a transition, the router first determines which routes are involved by beginning with the
248
+ * current route, up the route tree to the first parent route that is shared with the destination
249
+ * route, and back down the tree to the destination route. The willTransitionFrom hook is invoked
250
+ * on all route handlers we're transitioning away from, in reverse nesting order. Likewise, the
336
251
* willTransitionTo hook is invoked on all route handlers we're transitioning to.
337
252
*
338
- * Both willTransitionFrom and willTransitionTo hooks may either abort or redirect
339
- * the transition. To resolve asynchronously, they may use transition.wait(promise).
253
+ * Both willTransitionFrom and willTransitionTo hooks may either abort or redirect the transition.
254
+ * To resolve asynchronously, they may use transition.wait(promise). If no hooks wait, the
255
+ * transition will be synchronous.
340
256
*/
341
257
dispatch : function ( path , callback ) {
342
- if ( this . state . path === path )
343
- return callback ( ) ; // Nothing to do!
344
-
345
258
var transition = new Transition ( this , path ) ;
346
- var currentMatches = this . state . matches || [ ] ;
259
+ var currentMatches = this . state ? this . state . matches : [ ] ; // No state server-side.
347
260
var nextMatches = this . match ( path ) || [ ] ;
348
261
349
262
warning (
350
- nextMatches ,
263
+ nextMatches . length ,
351
264
'No route matches path "%s". Make sure you have <Route path="%s"> somewhere in your routes' ,
352
265
path , path
353
266
) ;
354
267
355
- computeNextState ( currentMatches , nextMatches , transition , function ( error , nextState ) {
356
- if ( error || transition . isAborted || nextState == null )
268
+ var fromMatches , toMatches ;
269
+ if ( currentMatches . length ) {
270
+ fromMatches = currentMatches . filter ( function ( match ) {
271
+ return ! hasMatch ( nextMatches , match ) ;
272
+ } ) ;
273
+
274
+ toMatches = nextMatches . filter ( function ( match ) {
275
+ return ! hasMatch ( currentMatches , match ) ;
276
+ } ) ;
277
+ } else {
278
+ fromMatches = [ ] ;
279
+ toMatches = nextMatches ;
280
+ }
281
+
282
+ var query = Path . extractQuery ( path ) || { } ;
283
+
284
+ runTransitionFromHooks ( fromMatches , transition , function ( error ) {
285
+ if ( error || transition . isAborted )
357
286
return callback ( error , transition . abortReason ) ;
358
287
359
- this . setState ( nextState , callback ) ;
360
- } . bind ( this ) ) ;
288
+ runTransitionToHooks ( toMatches , transition , query , function ( error ) {
289
+ if ( error || transition . isAborted )
290
+ return callback ( error , transition . abortReason ) ;
291
+
292
+ var matches = currentMatches . slice ( 0 , currentMatches . length - fromMatches . length ) . concat ( toMatches ) ;
293
+ var rootMatch = getRootMatch ( matches ) ;
294
+ var params = ( rootMatch && rootMatch . params ) || { } ;
295
+ var routes = matches . map ( function ( match ) {
296
+ return match . route ;
297
+ } ) ;
298
+
299
+ callback ( null , null , {
300
+ path : path ,
301
+ matches : matches ,
302
+ activeRoutes : routes ,
303
+ activeParams : params ,
304
+ activeQuery : query
305
+ } ) ;
306
+ } ) ;
307
+ } ) ;
361
308
} ,
362
309
363
310
/**
364
311
* Returns the props that should be used for the top-level route handler.
365
312
*/
366
313
getHandlerProps : function ( ) {
367
- return computeHandlerProps ( this . state . matches , this . state . activeQuery ) ;
314
+ var matches = this . state . matches ;
315
+ var query = this . state . activeQuery ;
316
+ var handler = returnNull ;
317
+ var props = {
318
+ ref : null ,
319
+ params : null ,
320
+ query : null ,
321
+ activeRouteHandler : handler ,
322
+ key : null
323
+ } ;
324
+
325
+ reversedArray ( matches ) . forEach ( function ( match ) {
326
+ var route = match . route ;
327
+
328
+ props = Route . getUnreservedProps ( route . props ) ;
329
+
330
+ props . ref = '__activeRoute__' ;
331
+ props . params = match . params ;
332
+ props . query = query ;
333
+ props . activeRouteHandler = handler ;
334
+
335
+ // TODO: Can we remove addHandlerKey?
336
+ if ( route . props . addHandlerKey )
337
+ props . key = Path . injectParams ( route . props . path , match . params ) ;
338
+
339
+ handler = function ( props , addedProps ) {
340
+ if ( arguments . length > 2 && typeof arguments [ 2 ] !== 'undefined' )
341
+ throw new Error ( 'Passing children to a route handler is not supported' ) ;
342
+
343
+ return route . props . handler (
344
+ copyProperties ( props , addedProps )
345
+ ) ;
346
+ } . bind ( this , props ) ;
347
+ } ) ;
348
+
349
+ return props ;
368
350
} ,
369
351
370
352
/**
0 commit comments