Skip to content

Commit 6c37f69

Browse files
hiebjJon Hieb
andauthored
fix: exitBeforeEnter in useTransition doesn't work when used with trail (#1868) (#2407)
Co-authored-by: Jon Hieb <hiebj@wildidea.io>
1 parent 2ff6de7 commit 6c37f69

File tree

3 files changed

+38
-6
lines changed

3 files changed

+38
-6
lines changed

.changeset/gentle-tomatoes-nail.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@react-spring/core': patch
3+
---
4+
5+
fix: exitBeforeEnter in useTransition doesn't work when used with trail

packages/core/src/hooks/useTransition.test.tsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,36 @@ describe('useTransition', () => {
195195

196196
expect(rendered).toEqual([1])
197197
})
198+
199+
it('should work with both exitBeforeEnter and trail together', async () => {
200+
const props = {
201+
from: { t: 0 },
202+
enter: { t: 1 },
203+
leave: { t: 0 },
204+
exitBeforeEnter: true,
205+
trail: 100,
206+
}
207+
208+
// Start with two items
209+
update([0, 1], props)
210+
expect(rendered).toEqual([0, 1])
211+
212+
global.mockRaf.step()
213+
214+
// Replace with two new items - the old ones should leave first with trail
215+
update([2, 3], props)
216+
217+
global.mockRaf.step()
218+
219+
// Old items should still be visible (leaving with trail)
220+
expect(rendered).toEqual([0, 1])
221+
222+
// Wait for all leave animations to complete
223+
await global.advanceUntilIdle()
224+
225+
// New items should now be visible
226+
expect(rendered).toEqual([2, 3])
227+
})
198228
})
199229

200230
let result: RenderResult | undefined

packages/core/src/hooks/useTransition.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,9 @@ export function useTransition(
307307
if (t.ctrl.idle) {
308308
const idle = transitions.every(t => t.ctrl.idle)
309309
if (t.phase == TransitionPhase.LEAVE) {
310+
// Remove this transition from exitingTransitions as soon as it completes.
311+
exitingTransitions.current.delete(t)
312+
310313
const expiry = callProp(expires, t.item)
311314
if (expiry !== false) {
312315
const expiryMs = expiry === true ? 0 : expiry
@@ -323,12 +326,6 @@ export function useTransition(
323326
}
324327
// Force update once idle and expired items exist.
325328
if (idle && transitions.some(t => t.expired)) {
326-
/**
327-
* Remove the exited transition from the list
328-
* this may not exist but we'll try anyway.
329-
*/
330-
exitingTransitions.current.delete(t)
331-
332329
if (exitBeforeEnter) {
333330
/**
334331
* If we have exitBeforeEnter == true

0 commit comments

Comments
 (0)