@@ -21,9 +21,8 @@ function hasAnyProperties(object) {
2121 * history objects that know about routing.
2222 *
2323 * - isActive(pathname, query)
24- * - registerRouteHook(route, (location) => {})
25- * - unregisterRouteHook(route, (location) => {})
2624 * - match(location, (error, nextState, nextLocation) => {})
25+ * - listenBeforeLeavingRoute(route, (?nextLocation) => {})
2726 * - listen((error, nextState) => {})
2827 */
2928function useRoutes ( createHistory ) {
@@ -88,14 +87,14 @@ function useRoutes(createHistory) {
8887 } )
8988 }
9089
91- const RouteHooks = { }
92-
9390 let RouteGuid = 1
9491
9592 function getRouteID ( route ) {
9693 return route . __id__ || ( route . __id__ = RouteGuid ++ )
9794 }
9895
96+ const RouteHooks = { }
97+
9998 function getRouteHooksForRoutes ( routes ) {
10099 return routes . reduce ( function ( hooks , route ) {
101100 hooks . push . apply ( hooks , RouteHooks [ getRouteID ( route ) ] )
@@ -133,8 +132,8 @@ function useRoutes(createHistory) {
133132 }
134133
135134 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.
138137 if ( state . routes ) {
139138 let hooks = getRouteHooksForRoutes ( state . routes )
140139
@@ -149,7 +148,22 @@ function useRoutes(createHistory) {
149148 }
150149 }
151150
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 ) {
153167 // TODO: Warn if they register for a route that isn't currently
154168 // active. They're probably doing something wrong, like re-creating
155169 // route objects on every location change.
@@ -162,34 +176,40 @@ function useRoutes(createHistory) {
162176 hooks = RouteHooks [ routeID ] = [ hook ]
163177
164178 if ( thereWereNoRouteHooks ) {
165- history . registerTransitionHook ( transitionHook )
179+ // setup transition & beforeunload hooks
180+ unlistenBefore = history . listenBefore ( transitionHook )
166181
167- if ( history . registerBeforeUnloadHook )
168- history . registerBeforeUnloadHook ( beforeUnloadHook )
182+ if ( history . listenBeforeUnload )
183+ unlistenBeforeUnload = history . listenBeforeUnload ( beforeUnloadHook )
169184 }
170185 } else if ( hooks . indexOf ( hook ) === - 1 ) {
171186 hooks . push ( hook )
172187 }
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
190212 }
191- } else {
192- RouteHooks [ routeID ] = newHooks
193213 }
194214 }
195215 }
@@ -229,10 +249,9 @@ function useRoutes(createHistory) {
229249 return {
230250 ...history ,
231251 isActive,
232- registerRouteHook,
233- unregisterRouteHook,
234- listen,
235- match
252+ match,
253+ listenBeforeLeavingRoute,
254+ listen
236255 }
237256 }
238257}
0 commit comments