Skip to content

Commit 8c71bd4

Browse files
authored
fix: make observe cleanup idempotent (#763)
1 parent b97fbaa commit 8c71bd4

2 files changed

Lines changed: 30 additions & 0 deletions

File tree

‎src/__tests__/observe.test.ts‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,32 @@ test("should be able to use observe", () => {
1919
);
2020
});
2121

22+
test("should only clean up each observer callback once", () => {
23+
const element = document.createElement("div");
24+
const firstCallback = vi.fn();
25+
const secondCallback = vi.fn();
26+
const firstCleanup = observe(element, firstCallback, { threshold: 0.1 });
27+
const secondCleanup = observe(element, secondCallback, { threshold: 0.1 });
28+
const observer = intersectionMockInstance(element);
29+
30+
firstCleanup();
31+
firstCleanup();
32+
mockIsIntersecting(element, true);
33+
34+
expect(firstCallback).not.toHaveBeenCalled();
35+
expect(secondCallback).toHaveBeenCalledTimes(1);
36+
expect(observer.unobserve).not.toHaveBeenCalled();
37+
38+
secondCleanup();
39+
expect(observer.unobserve).toHaveBeenCalledTimes(1);
40+
expect(observer.unobserve).toHaveBeenCalledWith(element);
41+
expect(observer.disconnect).toHaveBeenCalledTimes(1);
42+
43+
secondCleanup();
44+
expect(observer.unobserve).toHaveBeenCalledTimes(1);
45+
expect(observer.disconnect).toHaveBeenCalledTimes(1);
46+
});
47+
2248
test("should convert options to id", () => {
2349
expect(
2450
optionsToId({

‎src/observe.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,11 @@ export function observe(
156156
callbacks.push(callback);
157157
observer.observe(element);
158158

159+
let unobserved = false;
159160
return function unobserve() {
161+
if (unobserved) return;
162+
unobserved = true;
163+
160164
// Remove the callback from the callback list
161165
callbacks.splice(callbacks.indexOf(callback), 1);
162166

0 commit comments

Comments
 (0)