diff --git a/packages/next/client/use-intersection.tsx b/packages/next/client/use-intersection.tsx index 94ee9d97f1d1e..1b3a39db57d9d 100644 --- a/packages/next/client/use-intersection.tsx +++ b/packages/next/client/use-intersection.tsx @@ -13,8 +13,12 @@ type UseIntersection = { disabled?: boolean } & UseIntersectionObserverInit & { rootRef?: React.RefObject | null } type ObserveCallback = (isVisible: boolean) => void +type Identifier = { + root: Element | Document | null + margin: string +} type Observer = { - id: string + id: Identifier observer: IntersectionObserver elements: Map } @@ -83,14 +87,35 @@ function observe( if (elements.size === 0) { observer.disconnect() observers.delete(id) + let index = idList.findIndex( + (obj) => obj.root === id.root && obj.margin === id.margin + ) + if (index > -1) { + idList.splice(index, 1) + } } } } -const observers = new Map() +const observers = new Map() + +const idList: Identifier[] = [] + function createObserver(options: UseIntersectionObserverInit): Observer { - const id = options.rootMargin || '' - let instance = observers.get(id) + const id = { + root: options.root || null, + margin: options.rootMargin || '', + } + let existing = idList.find( + (obj) => obj.root === id.root && obj.margin === id.margin + ) + let instance + if (existing) { + instance = observers.get(existing) + } else { + instance = observers.get(id) + idList.push(id) + } if (instance) { return instance } diff --git a/test/integration/image-component/default/pages/lazy-noref.js b/test/integration/image-component/default/pages/lazy-noref.js deleted file mode 100644 index 3edfe7df79028..0000000000000 --- a/test/integration/image-component/default/pages/lazy-noref.js +++ /dev/null @@ -1,32 +0,0 @@ -import React, { useRef } from 'react' -import Image from 'next/image' - -const Page = () => { - const myRef = useRef(null) - - return ( - <> -
-
hello
-
- -
-
- - ) -} -export default Page diff --git a/test/integration/image-component/default/pages/lazy-withref.js b/test/integration/image-component/default/pages/lazy-withref.js index d21a4c0a9dad4..be990a9d4e7cd 100644 --- a/test/integration/image-component/default/pages/lazy-withref.js +++ b/test/integration/image-component/default/pages/lazy-withref.js @@ -18,13 +18,41 @@ const Page = () => {
hello
mine + mine + mine + + mine
diff --git a/test/integration/image-component/default/test/index.test.js b/test/integration/image-component/default/test/index.test.js index 35cad0906ac75..8267389e1c948 100644 --- a/test/integration/image-component/default/test/index.test.js +++ b/test/integration/image-component/default/test/index.test.js @@ -1010,15 +1010,49 @@ function runTests(mode) { } }) - it('should load the image when the lazyRoot prop is used', async () => { + it('should initially load only two of four images using lazyroot', async () => { let browser try { - //trying on '/lazy-noref' it fails browser = await webdriver(appPort, '/lazy-withref') + await check(async () => { + const result = await browser.eval( + `document.getElementById('myImage1').naturalWidth` + ) + + if (result >= 400) { + throw new Error('Incorrectly loaded image') + } + + return 'result-correct' + }, /result-correct/) + + await check(async () => { + const result = await browser.eval( + `document.getElementById('myImage4').naturalWidth` + ) + + if (result >= 400) { + throw new Error('Incorrectly loaded image') + } + + return 'result-correct' + }, /result-correct/) await check(async () => { const result = await browser.eval( - `document.getElementById('myImage').naturalWidth` + `document.getElementById('myImage2').naturalWidth` + ) + + if (result < 400) { + throw new Error('Incorrectly loaded image') + } + + return 'result-correct' + }, /result-correct/) + + await check(async () => { + const result = await browser.eval( + `document.getElementById('myImage3').naturalWidth` ) if (result < 400) { @@ -1033,7 +1067,25 @@ function runTests(mode) { browser, `http://localhost:${appPort}/_next/image?url=%2Ftest.jpg&w=828&q=75` ) + ).toBe(false) + expect( + await hasImageMatchingUrl( + browser, + `http://localhost:${appPort}/_next/image?url=%2Ftest.png&w=828&q=75` + ) + ).toBe(true) + expect( + await hasImageMatchingUrl( + browser, + `http://localhost:${appPort}/_next/image?url=%2Ftest.svg&w=828&q=75` + ) ).toBe(true) + expect( + await hasImageMatchingUrl( + browser, + `http://localhost:${appPort}/_next/image?url=%2Ftest.webp&w=828&q=75` + ) + ).toBe(false) } finally { if (browser) { await browser.close()