From 088ae28784f39b55645a33d1ae2bdb3e1f2de3a0 Mon Sep 17 00:00:00 2001 From: Steven Date: Thu, 14 Apr 2022 19:25:36 -0400 Subject: [PATCH] Fix `next/image` usage in most cases of `onLoad()` --- packages/next/client/image.tsx | 4 + .../image-component/default/pages/on-load.js | 101 ++++++++++++++++++ .../default/test/index.test.js | 74 +++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 test/integration/image-component/default/pages/on-load.js diff --git a/packages/next/client/image.tsx b/packages/next/client/image.tsx index 5eea24447eab361..6a793cdae1cd7b8 100644 --- a/packages/next/client/image.tsx +++ b/packages/next/client/image.tsx @@ -884,6 +884,7 @@ const ImageElement = ({ onLoadingCompleteRef, setBlurComplete, setIntersection, + onLoad, onError, isVisible, ...rest @@ -933,6 +934,9 @@ const ImageElement = ({ onLoadingCompleteRef, setBlurComplete ) + if (onLoad) { + onLoad(event) + } }} onError={(event) => { if (placeholder === 'blur') { diff --git a/test/integration/image-component/default/pages/on-load.js b/test/integration/image-component/default/pages/on-load.js new file mode 100644 index 000000000000000..81b9b4cb0172559 --- /dev/null +++ b/test/integration/image-component/default/pages/on-load.js @@ -0,0 +1,101 @@ +import { useState } from 'react' +import Image from 'next/image' + +const Page = () => { + // Hoisted state to count each image load callback + const [idToCount, setIdToCount] = useState({}) + const [clicked, setClicked] = useState(false) + + return ( +
+

Test onLoad

+

+ This is the native onLoad which doesn't work as many places as + onLoadingComplete +

+ + + + + + + + + + + + + ) +} + +function ImageWithMessage({ id, idToCount, setIdToCount, ...props }) { + const [msg, setMsg] = useState('[LOADING]') + const style = + props.layout === 'fill' + ? { position: 'relative', width: '64px', height: '64px' } + : {} + return ( + <> +
+ { + let count = idToCount[id] || 0 + count++ + idToCount[id] = count + setIdToCount(idToCount) + const msg = `loaded ${count} ${e.target.id} with native onLoad` + setMsg(msg) + console.log(msg) + }} + {...props} + /> +
+

{msg}

+
+ + ) +} + +export default Page diff --git a/test/integration/image-component/default/test/index.test.js b/test/integration/image-component/default/test/index.test.js index fc09281dec0c132..a9d2ab902bad483 100644 --- a/test/integration/image-component/default/test/index.test.js +++ b/test/integration/image-component/default/test/index.test.js @@ -289,6 +289,80 @@ function runTests(mode) { } }) + it('should callback native onLoad in most cases', async () => { + let browser = await webdriver(appPort, '/on-load') + + await browser.eval( + `document.getElementById("footer").scrollIntoView({behavior: "smooth"})` + ) + + await check( + () => browser.eval(`document.getElementById("img1").currentSrc`), + /test(.*)jpg/ + ) + await check( + () => browser.eval(`document.getElementById("img2").currentSrc`), + /test(.*).png/ + ) + await check( + () => browser.eval(`document.getElementById("img3").currentSrc`), + /test\.svg/ + ) + await check( + () => browser.eval(`document.getElementById("img4").currentSrc`), + /test(.*)ico/ + ) + await check( + () => browser.eval(`document.getElementById("msg1").textContent`), + 'loaded 1 img1 with native onLoad' + ) + await check( + () => browser.eval(`document.getElementById("msg2").textContent`), + 'loaded 1 img2 with native onLoad' + ) + await check( + () => browser.eval(`document.getElementById("msg3").textContent`), + 'loaded 1 img3 with native onLoad' + ) + await check( + () => browser.eval(`document.getElementById("msg4").textContent`), + 'loaded 1 img4 with native onLoad' + ) + await check( + () => browser.eval(`document.getElementById("msg8").textContent`), + 'loaded 1 img8 with native onLoad' + ) + await check( + () => + browser.eval( + `document.getElementById("img8").getAttribute("data-nimg")` + ), + 'intrinsic' + ) + await check( + () => browser.eval(`document.getElementById("img8").currentSrc`), + /wide.png/ + ) + await browser.eval('document.getElementById("toggle").click()') + // The normal `onLoad()` is triggered by lazy placeholder image + // so ideally this would be "2" instead of "3" count + await check( + () => browser.eval(`document.getElementById("msg8").textContent`), + 'loaded 3 img8 with native onLoad' + ) + await check( + () => + browser.eval( + `document.getElementById("img8").getAttribute("data-nimg")` + ), + 'fixed' + ) + await check( + () => browser.eval(`document.getElementById("img8").currentSrc`), + /test-rect.jpg/ + ) + }) + it('should work with image with blob src', async () => { let browser try {