Skip to content

Commit

Permalink
[changed] Removed (un)registerRouteHook
Browse files Browse the repository at this point in the history
Use listenBeforeLeavingRoute instead.
  • Loading branch information
mjackson committed Sep 24, 2015
1 parent 08ada07 commit b8f1abe
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 51 deletions.
34 changes: 16 additions & 18 deletions modules/Lifecycle.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@ import invariant from 'invariant'

const { object } = React.PropTypes

function getRoute(element) {
const route = element.props.route || element.context.route

invariant(
route,
'The Lifecycle mixin needs to be used either on 1) a <Route component> or ' +
'2) a descendant of a <Route component> that uses the RouteContext mixin'
)

return route
}

/**
* The Lifecycle mixin adds the routerWillLeave lifecycle method
* to a component that may be used to cancel a transition or prompt
Expand Down Expand Up @@ -33,35 +45,21 @@ const Lifecycle = {
route: object
},

_getRoute() {
const route = this.props.route || this.context.route

invariant(
route,
'The Lifecycle mixin needs to be used either on 1) a <Route component> or ' +
'2) a descendant of a <Route component> that uses the RouteContext mixin'
)

return route
},

componentWillMount() {
invariant(
this.routerWillLeave,
'The Lifecycle mixin requires you to define a routerWillLeave method'
)

this.context.history.registerRouteHook(
this._getRoute(),
this._unlistenBeforeLeavingRoute = this.context.history.listenBeforeLeavingRoute(
getRoute(this),
this.routerWillLeave
)
},

componentWillUnmount() {
this.context.history.unregisterRouteHook(
this._getRoute(),
this.routerWillLeave
)
if (this._unlistenBeforeLeavingRoute)
this._unlistenBeforeLeavingRoute()
}

}
Expand Down
85 changes: 52 additions & 33 deletions modules/useRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ function hasAnyProperties(object) {
* history objects that know about routing.
*
* - isActive(pathname, query)
* - registerRouteHook(route, (location) => {})
* - unregisterRouteHook(route, (location) => {})
* - match(location, (error, nextState, nextLocation) => {})
* - listenBeforeLeavingRoute(route, (?nextLocation) => {})
* - listen((error, nextState) => {})
*/
function useRoutes(createHistory) {
Expand Down Expand Up @@ -88,14 +87,14 @@ function useRoutes(createHistory) {
})
}

const RouteHooks = {}

let RouteGuid = 1

function getRouteID(route) {
return route.__id__ || (route.__id__ = RouteGuid++)
}

const RouteHooks = {}

function getRouteHooksForRoutes(routes) {
return routes.reduce(function (hooks, route) {
hooks.push.apply(hooks, RouteHooks[getRouteID(route)])
Expand Down Expand Up @@ -133,8 +132,8 @@ function useRoutes(createHistory) {
}

function beforeUnloadHook() {
// Synchronously check to see if any route hooks want to
// prevent the current window/tab from closing.
// Synchronously check to see if any route hooks want
// to prevent the current window/tab from closing.
if (state.routes) {
let hooks = getRouteHooksForRoutes(state.routes)

Expand All @@ -149,7 +148,22 @@ function useRoutes(createHistory) {
}
}

function registerRouteHook(route, hook) {
let unlistenBefore, unlistenBeforeUnload

/**
* Registers the given hook function to run before leaving the given route.
*
* During a normal transition, the hook function receives the next location
* as its only argument and must return either a) a prompt message to show
* the user, to make sure they want to leave the page or b) false, to prevent
* the transition.
*
* During the beforeunload event (in browsers) the hook receives no arguments.
* In this case it must return a prompt message to prevent the transition.
*
* Returns a function that may be used to unbind the listener.
*/
function listenBeforeLeavingRoute(route, hook) {
// TODO: Warn if they register for a route that isn't currently
// active. They're probably doing something wrong, like re-creating
// route objects on every location change.
Expand All @@ -162,34 +176,40 @@ function useRoutes(createHistory) {
hooks = RouteHooks[routeID] = [ hook ]

if (thereWereNoRouteHooks) {
history.registerTransitionHook(transitionHook)
// setup transition & beforeunload hooks
unlistenBefore = history.listenBefore(transitionHook)

if (history.registerBeforeUnloadHook)
history.registerBeforeUnloadHook(beforeUnloadHook)
if (history.listenBeforeUnload)
unlistenBeforeUnload = history.listenBeforeUnload(beforeUnloadHook)
}
} else if (hooks.indexOf(hook) === -1) {
hooks.push(hook)
}
}

function unregisterRouteHook(route, hook) {
let routeID = getRouteID(route)
let hooks = RouteHooks[routeID]

if (hooks != null) {
let newHooks = hooks.filter(item => item !== hook)

if (newHooks.length === 0) {
delete RouteHooks[routeID]

if (!hasAnyProperties(RouteHooks)) {
history.unregisterTransitionHook(transitionHook)

if (history.unregisterBeforeUnloadHook)
history.unregisterBeforeUnloadHook(beforeUnloadHook)

return function () {
let hooks = RouteHooks[routeID]

if (hooks != null) {
let newHooks = hooks.filter(item => item !== hook)

if (newHooks.length === 0) {
delete RouteHooks[routeID]

if (!hasAnyProperties(RouteHooks)) {
// teardown transition & beforeunload hooks
if (unlistenBefore) {
unlistenBefore()
unlistenBefore = null
}

if (unlistenBeforeUnload) {
unlistenBeforeUnload()
unlistenBeforeUnload = null
}
}
} else {
RouteHooks[routeID] = newHooks
}
} else {
RouteHooks[routeID] = newHooks
}
}
}
Expand Down Expand Up @@ -229,10 +249,9 @@ function useRoutes(createHistory) {
return {
...history,
isActive,
registerRouteHook,
unregisterRouteHook,
listen,
match
match,
listenBeforeLeavingRoute,
listen
}
}
}
Expand Down

0 comments on commit b8f1abe

Please sign in to comment.