Skip to content

Commit 6bdff14

Browse files
authored
Merge pull request #3313 from motiondivision/fix/spring-value-cleanup
Fix `springValue` cleanup
2 parents 30e9fc6 + 80cb78a commit 6bdff14

File tree

2 files changed

+50
-12
lines changed

2 files changed

+50
-12
lines changed

packages/motion-dom/src/value/__tests__/spring-value.test.ts

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { syncDriver } from "../../animation/__tests__/utils"
22
import { motionValue } from "../index"
3-
import { springValue } from "../spring-value"
3+
import { attachSpring, springValue } from "../spring-value"
44

55
describe("springValue types", () => {
66
test("can create a motion value from a number", () => {
@@ -140,16 +140,49 @@ const runSpringTests = (unit?: string | undefined) => {
140140
expect(resolved).toEqual([createValue(100)])
141141
})
142142

143-
test("unsubscribes when destroyed", () => {
144-
const a = motionValue(createValue(0))
143+
test("unsubscribes when spring is destroyed", () => {
144+
const source = motionValue(createValue(0))
145+
const spring = springValue(source)
145146

146-
const b = springValue(a)
147-
springValue(a)
147+
expect((source as any).events.change.getSize()).toBe(1)
148+
expect((spring as any).events.destroy.getSize()).toBe(1)
148149

149-
b.destroy()
150+
spring.destroy()
150151

151152
// Cast to any here as `.events` is private API
152-
expect((a as any).events.change.getSize()).toBe(1)
153+
expect((source as any).events.change.getSize()).toBe(0)
154+
expect((spring as any).events.destroy.getSize()).toBe(0)
155+
})
156+
157+
test("unsubscribes when source is destroyed", () => {
158+
const source = motionValue(createValue(0))
159+
springValue(source)
160+
161+
expect((source as any).events.change.getSize()).toBe(1)
162+
163+
source.destroy()
164+
165+
// Cast to any here as `.events` is private API
166+
expect((source as any).events.change.getSize()).toBe(0)
167+
})
168+
169+
test("Cleanup function works as expected", () => {
170+
const source = motionValue(createValue(0))
171+
const spring = motionValue(createValue(0))
172+
173+
const clean = attachSpring(spring, source)
174+
clean()
175+
const clean2 = attachSpring(spring, source)
176+
177+
expect((source as any).events.change.getSize()).toBe(1)
178+
expect((spring as any).events.destroy.getSize()).toBe(1)
179+
180+
clean2()
181+
const clean3 = attachSpring(spring, source)
182+
clean3()
183+
184+
expect((source as any).events.change.getSize()).toBe(0)
185+
expect((spring as any).events.destroy.getSize()).toBe(0)
153186
})
154187
})
155188
}

packages/motion-dom/src/value/spring-value.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export function attachSpring<T extends AnyResolvedKeyframe>(
3434
value: MotionValue<T>,
3535
source: T | MotionValue<T>,
3636
options?: SpringOptions
37-
) {
37+
): VoidFunction {
3838
const initialValue = value.get()
3939

4040
let activeAnimation: JSAnimation<number> | null = null
@@ -75,15 +75,20 @@ export function attachSpring<T extends AnyResolvedKeyframe>(
7575
return value.get()
7676
}, stopAnimation)
7777

78-
let unsubscribe: VoidFunction | undefined = undefined
7978
if (isMotionValue(source)) {
80-
unsubscribe = source.on("change", (v) =>
79+
const removeSourceOnChange = source.on("change", (v) =>
8180
value.set(parseValue(v, unit) as T)
8281
)
83-
value.on("destroy", unsubscribe)
82+
83+
const removeValueOnDestroy = value.on("destroy", removeSourceOnChange)
84+
85+
return () => {
86+
removeSourceOnChange()
87+
removeValueOnDestroy()
88+
}
8489
}
8590

86-
return unsubscribe
91+
return stopAnimation
8792
}
8893

8994
function parseValue(v: AnyResolvedKeyframe, unit?: string) {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy