@@ -21,9 +21,8 @@ function hasAnyProperties(object) {
21
21
* history objects that know about routing.
22
22
*
23
23
* - isActive(pathname, query)
24
- * - registerRouteHook(route, (location) => {})
25
- * - unregisterRouteHook(route, (location) => {})
26
24
* - match(location, (error, nextState, nextLocation) => {})
25
+ * - listenBeforeLeavingRoute(route, (?nextLocation) => {})
27
26
* - listen((error, nextState) => {})
28
27
*/
29
28
function useRoutes ( createHistory ) {
@@ -88,14 +87,14 @@ function useRoutes(createHistory) {
88
87
} )
89
88
}
90
89
91
- const RouteHooks = { }
92
-
93
90
let RouteGuid = 1
94
91
95
92
function getRouteID ( route ) {
96
93
return route . __id__ || ( route . __id__ = RouteGuid ++ )
97
94
}
98
95
96
+ const RouteHooks = { }
97
+
99
98
function getRouteHooksForRoutes ( routes ) {
100
99
return routes . reduce ( function ( hooks , route ) {
101
100
hooks . push . apply ( hooks , RouteHooks [ getRouteID ( route ) ] )
@@ -133,8 +132,8 @@ function useRoutes(createHistory) {
133
132
}
134
133
135
134
function beforeUnloadHook ( ) {
136
- // Synchronously check to see if any route hooks want to
137
- // prevent the current window/tab from closing.
135
+ // Synchronously check to see if any route hooks want
136
+ // to prevent the current window/tab from closing.
138
137
if ( state . routes ) {
139
138
let hooks = getRouteHooksForRoutes ( state . routes )
140
139
@@ -149,7 +148,22 @@ function useRoutes(createHistory) {
149
148
}
150
149
}
151
150
152
- function registerRouteHook ( route , hook ) {
151
+ let unlistenBefore , unlistenBeforeUnload
152
+
153
+ /**
154
+ * Registers the given hook function to run before leaving the given route.
155
+ *
156
+ * During a normal transition, the hook function receives the next location
157
+ * as its only argument and must return either a) a prompt message to show
158
+ * the user, to make sure they want to leave the page or b) false, to prevent
159
+ * the transition.
160
+ *
161
+ * During the beforeunload event (in browsers) the hook receives no arguments.
162
+ * In this case it must return a prompt message to prevent the transition.
163
+ *
164
+ * Returns a function that may be used to unbind the listener.
165
+ */
166
+ function listenBeforeLeavingRoute ( route , hook ) {
153
167
// TODO: Warn if they register for a route that isn't currently
154
168
// active. They're probably doing something wrong, like re-creating
155
169
// route objects on every location change.
@@ -162,34 +176,40 @@ function useRoutes(createHistory) {
162
176
hooks = RouteHooks [ routeID ] = [ hook ]
163
177
164
178
if ( thereWereNoRouteHooks ) {
165
- history . registerTransitionHook ( transitionHook )
179
+ // setup transition & beforeunload hooks
180
+ unlistenBefore = history . listenBefore ( transitionHook )
166
181
167
- if ( history . registerBeforeUnloadHook )
168
- history . registerBeforeUnloadHook ( beforeUnloadHook )
182
+ if ( history . listenBeforeUnload )
183
+ unlistenBeforeUnload = history . listenBeforeUnload ( beforeUnloadHook )
169
184
}
170
185
} else if ( hooks . indexOf ( hook ) === - 1 ) {
171
186
hooks . push ( hook )
172
187
}
173
- }
174
-
175
- function unregisterRouteHook ( route , hook ) {
176
- let routeID = getRouteID ( route )
177
- let hooks = RouteHooks [ routeID ]
178
-
179
- if ( hooks != null ) {
180
- let newHooks = hooks . filter ( item => item !== hook )
181
-
182
- if ( newHooks . length === 0 ) {
183
- delete RouteHooks [ routeID ]
184
-
185
- if ( ! hasAnyProperties ( RouteHooks ) ) {
186
- history . unregisterTransitionHook ( transitionHook )
187
-
188
- if ( history . unregisterBeforeUnloadHook )
189
- history . unregisterBeforeUnloadHook ( beforeUnloadHook )
188
+
189
+ return function ( ) {
190
+ let hooks = RouteHooks [ routeID ]
191
+
192
+ if ( hooks != null ) {
193
+ let newHooks = hooks . filter ( item => item !== hook )
194
+
195
+ if ( newHooks . length === 0 ) {
196
+ delete RouteHooks [ routeID ]
197
+
198
+ if ( ! hasAnyProperties ( RouteHooks ) ) {
199
+ // teardown transition & beforeunload hooks
200
+ if ( unlistenBefore ) {
201
+ unlistenBefore ( )
202
+ unlistenBefore = null
203
+ }
204
+
205
+ if ( unlistenBeforeUnload ) {
206
+ unlistenBeforeUnload ( )
207
+ unlistenBeforeUnload = null
208
+ }
209
+ }
210
+ } else {
211
+ RouteHooks [ routeID ] = newHooks
190
212
}
191
- } else {
192
- RouteHooks [ routeID ] = newHooks
193
213
}
194
214
}
195
215
}
@@ -229,10 +249,9 @@ function useRoutes(createHistory) {
229
249
return {
230
250
...history ,
231
251
isActive,
232
- registerRouteHook,
233
- unregisterRouteHook,
234
- listen,
235
- match
252
+ match,
253
+ listenBeforeLeavingRoute,
254
+ listen
236
255
}
237
256
}
238
257
}
0 commit comments