Skip to content

Commit 6ea547e

Browse files
committed
Merge pull request #3166 from reactjs/transition-bug
Transition bug
2 parents 837d21b + d5747e9 commit 6ea547e

File tree

3 files changed

+64
-5
lines changed

3 files changed

+64
-5
lines changed

CHANGES.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
## [HEAD]
22
> Unreleased
33
4-
- Nothing yet!
4+
- Fixed bug where transition hooks were not called on child routes of
5+
parent's whose params changed but the child's did not. ([#3166])
6+
7+
[#3166][https://github.com/reactjs/react-router/pull/3166]
58

69
[HEAD]: https://github.com/reactjs/react-router/compare/v2.0.0...HEAD
710

modules/__tests__/transitionHooks-test.js

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ describe('When a router enters a branch', function () {
1010
let
1111
node,
1212
newsLeaveHookSpy, removeNewsLeaveHook, userLeaveHookSpy,
13-
DashboardRoute, NewsFeedRoute, InboxRoute, RedirectToInboxRoute, MessageRoute, UserRoute,
13+
DashboardRoute, NewsFeedRoute, InboxRoute, RedirectToInboxRoute, MessageRoute, UserRoute, AssignmentRoute,
1414
routes
1515

1616
beforeEach(function () {
@@ -52,6 +52,12 @@ describe('When a router enters a branch', function () {
5252
}
5353
}
5454

55+
class UserAssignment extends Component {
56+
render() {
57+
return <div>assignment {this.props.params.assignmentId}</div>
58+
}
59+
}
60+
5561
class User extends Component {
5662
componentWillMount() {
5763
this.context.router.setRouteLeaveHook(
@@ -61,7 +67,7 @@ describe('When a router enters a branch', function () {
6167
}
6268

6369
render() {
64-
return <div>User</div>
70+
return <div>User {this.props.params.userId} {this.props.children}</div>
6571
}
6672
}
6773

@@ -121,9 +127,19 @@ describe('When a router enters a branch', function () {
121127
}
122128
}
123129

130+
AssignmentRoute = {
131+
path: 'assignments/:assignmentId',
132+
component: UserAssignment,
133+
onEnter() { expect(this).toBe(AssignmentRoute) },
134+
onLeave() { expect(this).toBe(AssignmentRoute) }
135+
}
136+
124137
UserRoute = {
125138
path: 'users/:userId',
126-
component: User
139+
component: User,
140+
childRoutes: [ AssignmentRoute ],
141+
onEnter() { expect(this).toBe(UserRoute) },
142+
onLeave() { expect(this).toBe(UserRoute) }
127143
}
128144

129145
DashboardRoute = {
@@ -277,6 +293,38 @@ describe('When a router enters a branch', function () {
277293
})
278294
})
279295

296+
describe('and then navigates to the same branch, but with different parent params', function () {
297+
it('calls the onLeave and onEnter hooks of the parent and children', function (done) {
298+
const parentLeaveSpy = spyOn(UserRoute, 'onLeave').andCallThrough()
299+
const parentEnterSpy = spyOn(UserRoute, 'onEnter').andCallThrough()
300+
const childLeaveSpy = spyOn(AssignmentRoute, 'onLeave').andCallThrough()
301+
const childEnterSpy = spyOn(AssignmentRoute, 'onEnter').andCallThrough()
302+
const history = createHistory('/users/123/assignments/456')
303+
304+
const steps = [
305+
function () {
306+
expect(parentEnterSpy).toHaveBeenCalled()
307+
expect(childEnterSpy).toHaveBeenCalled()
308+
history.push('/users/789/assignments/456')
309+
},
310+
function () {
311+
expect(parentLeaveSpy).toHaveBeenCalled()
312+
expect(childLeaveSpy).toHaveBeenCalled()
313+
expect(parentEnterSpy).toHaveBeenCalled()
314+
expect(childEnterSpy).toHaveBeenCalled()
315+
}
316+
]
317+
318+
const execNextStep = execSteps(steps, done)
319+
320+
render(
321+
<Router history={history}
322+
routes={routes}
323+
onUpdate={execNextStep}
324+
/>, node, execNextStep)
325+
})
326+
})
327+
280328
describe('and then the query changes', function () {
281329
it('calls the onEnter hooks of all routes in that branch', function (done) {
282330
const newsFeedRouteEnterSpy = spyOn(NewsFeedRoute, 'onEnter').andCallThrough()

modules/computeChangedRoutes.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,16 @@ function computeChangedRoutes(prevState, nextState) {
2727

2828
let leaveRoutes, enterRoutes
2929
if (prevRoutes) {
30+
let parentIsLeaving = false
3031
leaveRoutes = prevRoutes.filter(function (route) {
31-
return nextRoutes.indexOf(route) === -1 || routeParamsChanged(route, prevState, nextState)
32+
if (parentIsLeaving) {
33+
return true
34+
} else {
35+
const isLeaving = nextRoutes.indexOf(route) === -1 || routeParamsChanged(route, prevState, nextState)
36+
if (isLeaving)
37+
parentIsLeaving = true
38+
return isLeaving
39+
}
3240
})
3341

3442
// onLeave hooks start at the leaf route.

0 commit comments

Comments
 (0)