From 15b463b697349de3da9884d95a26dbecb495b585 Mon Sep 17 00:00:00 2001 From: Steven Date: Tue, 17 Oct 2023 11:06:35 -0400 Subject: [PATCH 1/3] chore(next/image)!: mark `onLoadingComplete` as deprecated in favor of `onLoad` --- .../02-api-reference/01-components/image.mdx | 44 ++++++++++--------- .../components/SharedModal.tsx | 2 +- examples/with-sfcc/components/ProductCard.tsx | 2 +- packages/next/src/shared/lib/get-img-props.ts | 12 ++++- .../next-image-new/app-dir/test/index.test.ts | 7 +++ 5 files changed, 43 insertions(+), 24 deletions(-) diff --git a/docs/02-app/02-api-reference/01-components/image.mdx b/docs/02-app/02-api-reference/01-components/image.mdx index d7d0121fe5ad0..8d09e45aa4c6b 100644 --- a/docs/02-app/02-api-reference/01-components/image.mdx +++ b/docs/02-app/02-api-reference/01-components/image.mdx @@ -40,24 +40,24 @@ export default function Page() { Here's a summary of the props available for the Image Component:
-| Prop | Example | Type | Required | -| ----------------------------------------- | ------------------------------------ | --------------- | -------- | -| [`src`](#src) | `src="/profile.png"` | String | Yes | -| [`width`](#width) | `width={500}` | Integer (px) | Yes | -| [`height`](#height) | `height={500}` | Integer (px) | Yes | -| [`alt`](#alt) | `alt="Picture of the author"` | String | Yes | -| [`loader`](#loader) | `loader={imageLoader}` | Function | - | -| [`fill`](#fill) | `fill={true}` | Boolean | - | -| [`sizes`](#sizes) | `sizes="(max-width: 768px) 100vw"` | String | - | -| [`quality`](#quality) | `quality={80}` | Integer (1-100) | - | -| [`priority`](#priority) | `priority={true}` | Boolean | - | -| [`placeholder`](#placeholder) | `placeholder="blur"` | String | - | -| [`style`](#style) | `style={{objectFit: "contain"}}` | Object | - | -| [`onLoadingComplete`](#onloadingcomplete) | `onLoadingComplete={img => done())}` | Function | - | -| [`onLoad`](#onload) | `onLoad={event => done())}` | Function | - | -| [`onError`](#onerror) | `onError(event => fail()}` | Function | - | -| [`loading`](#loading) | `loading="lazy"` | String | - | -| [`blurDataURL`](#blurdataurl) | `blurDataURL="data:image/jpeg..."` | String | - | +| Prop | Example | Type | Status | +| ----------------------------------------- | ------------------------------------ | --------------- | ---------- | +| [`src`](#src) | `src="/profile.png"` | String | Required | +| [`width`](#width) | `width={500}` | Integer (px) | Required | +| [`height`](#height) | `height={500}` | Integer (px) | Required | +| [`alt`](#alt) | `alt="Picture of the author"` | String | Required | +| [`loader`](#loader) | `loader={imageLoader}` | Function | - | +| [`fill`](#fill) | `fill={true}` | Boolean | - | +| [`sizes`](#sizes) | `sizes="(max-width: 768px) 100vw"` | String | - | +| [`quality`](#quality) | `quality={80}` | Integer (1-100) | - | +| [`priority`](#priority) | `priority={true}` | Boolean | - | +| [`placeholder`](#placeholder) | `placeholder="blur"` | String | - | +| [`style`](#style) | `style={{objectFit: "contain"}}` | Object | - | +| [`onLoadingComplete`](#onloadingcomplete) | `onLoadingComplete={img => done())}` | Function | Deprecated | +| [`onLoad`](#onload) | `onLoad={event => done())}` | Function | - | +| [`onError`](#onerror) | `onError(event => fail()}` | Function | - | +| [`loading`](#loading) | `loading="lazy"` | String | - | +| [`blurDataURL`](#blurdataurl) | `blurDataURL="data:image/jpeg..."` | String | - |
## Required Props @@ -286,6 +286,8 @@ Remember that the required width and height props can interact with your styling console.log(img.naturalWidth)} /> ``` +> **Warning**: Deprecated since Next.js 14 in favor of [`onLoad`](#onload). + A callback function that is invoked once the image is completely loaded and the [placeholder](#placeholder) has been removed. The callback function will be called with one argument, a reference to the underlying `` element. @@ -302,9 +304,9 @@ The callback function will be called with one argument, a reference to the under console.log(e.target.naturalWidth)} /> ``` -A callback function that is invoked when the image is loaded. +A callback function that is invoked once the image is completely loaded and the [placeholder](#placeholder) has been removed. -The load event might occur before the image placeholder is removed and the image is fully decoded. If you want to wait until the image has fully loaded, use [`onLoadingComplete`](#onloadingcomplete) instead. +The callback function will be called with one argument, the Event which has a `target` that references the underlying `` element. @@ -445,7 +447,7 @@ The `**` syntax does not work in the middle of the pattern. ### `domains` -> **Warning**: We recommend configuring strict [`remotePatterns`](#remotepatterns) instead of `domains` in order to protect your application from malicious users. Only use `domains` if you own all the content served from the domain. +> **Warning**: Deprecated since Next.js 14. We recommend configuring strict [`remotePatterns`](#remotepatterns) instead of `domains` in order to protect your application from malicious users. Only use `domains` if you own all the content served from the domain. Similar to [`remotePatterns`](#remotepatterns), the `domains` configuration can be used to provide a list of allowed hostnames for external images. diff --git a/examples/with-cloudinary/components/SharedModal.tsx b/examples/with-cloudinary/components/SharedModal.tsx index 5d738b114fc29..42f102dd50d4d 100644 --- a/examples/with-cloudinary/components/SharedModal.tsx +++ b/examples/with-cloudinary/components/SharedModal.tsx @@ -81,7 +81,7 @@ export default function SharedModal({ height={navigation ? 853 : 1280} priority alt="Next.js Conf image" - onLoadingComplete={() => setLoaded(true)} + onLoad={() => setLoaded(true)} /> diff --git a/examples/with-sfcc/components/ProductCard.tsx b/examples/with-sfcc/components/ProductCard.tsx index aceaf9664395e..9fe5be89ef612 100644 --- a/examples/with-sfcc/components/ProductCard.tsx +++ b/examples/with-sfcc/components/ProductCard.tsx @@ -22,7 +22,7 @@ export default function ProductCard({ product }) { ? 'scale-110 blur-2xl grayscale' : 'scale-100 blur-0 grayscale-0' )} - onLoadingComplete={() => setLoading(false)} + onLoad={() => setLoading(false)} />
diff --git a/packages/next/src/shared/lib/get-img-props.ts b/packages/next/src/shared/lib/get-img-props.ts index def521b0b1f7f..a4d38baa085e0 100644 --- a/packages/next/src/shared/lib/get-img-props.ts +++ b/packages/next/src/shared/lib/get-img-props.ts @@ -38,6 +38,10 @@ export type ImageProps = Omit< placeholder?: PlaceholderValue blurDataURL?: string unoptimized?: boolean + /** + * @deprecated Use `onLoad` instead. + * @see https://nextjs.org/docs/app/api-reference/components/image#onload + */ onLoadingComplete?: OnLoadingComplete /** * @deprecated Use `fill` prop instead of `layout="fill"` or change import to `next/legacy/image`. @@ -500,7 +504,7 @@ export function getImgProps( } if ('ref' in rest) { warnOnce( - `Image with src "${src}" is using unsupported "ref" property. Consider using the "onLoadingComplete" property instead.` + `Image with src "${src}" is using unsupported "ref" property. Consider using the "onLoad" property instead.` ) } @@ -523,6 +527,12 @@ export function getImgProps( } } + if (onLoadingComplete) { + warnOnce( + `Image with src "${src}" is using deprecated "onLoadingComplete" property. Please use the "onLoad" property instead.` + ) + } + for (const [legacyKey, legacyValue] of Object.entries({ layout, objectFit, diff --git a/test/integration/next-image-new/app-dir/test/index.test.ts b/test/integration/next-image-new/app-dir/test/index.test.ts index 1e3b847677758..170c7a1576063 100644 --- a/test/integration/next-image-new/app-dir/test/index.test.ts +++ b/test/integration/next-image-new/app-dir/test/index.test.ts @@ -357,6 +357,13 @@ function runTests(mode) { () => browser.eval(`document.getElementById("msg9").textContent`), 'loaded 1 img9 with dimensions 400x400' ) + + const warnings = (await browser.log('browser')) + .map((log) => log.message) + .join('\n') + expect(warnings).toMatch( + /Image with src "\/test\.jpg" is using deprecated "onLoadingComplete" property. Please use the "onLoad" property instead./gm + ) }) it('should callback native onLoad with sythetic event', async () => { From f71c17012f59fc2908d18a7657e10bebf8c2a98d Mon Sep 17 00:00:00 2001 From: Steven Date: Tue, 17 Oct 2023 11:26:59 -0400 Subject: [PATCH 2/3] fix regex pattern in test --- test/integration/next-image-new/app-dir/test/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/next-image-new/app-dir/test/index.test.ts b/test/integration/next-image-new/app-dir/test/index.test.ts index 170c7a1576063..89f6837a0f1f9 100644 --- a/test/integration/next-image-new/app-dir/test/index.test.ts +++ b/test/integration/next-image-new/app-dir/test/index.test.ts @@ -362,7 +362,7 @@ function runTests(mode) { .map((log) => log.message) .join('\n') expect(warnings).toMatch( - /Image with src "\/test\.jpg" is using deprecated "onLoadingComplete" property. Please use the "onLoad" property instead./gm + /Image with src "(.*)test(.*)jpg" is using deprecated "onLoadingComplete" property. Please use the "onLoad" property instead./gm ) }) From d6283380c76200787cad8cd618e45f2533a7c9d0 Mon Sep 17 00:00:00 2001 From: Steven Date: Tue, 17 Oct 2023 14:39:47 -0400 Subject: [PATCH 3/3] only check for warning in dev --- .../next-image-new/app-dir/test/index.test.ts | 14 ++++++++------ .../next-image-new/default/test/index.test.ts | 9 +++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/test/integration/next-image-new/app-dir/test/index.test.ts b/test/integration/next-image-new/app-dir/test/index.test.ts index 89f6837a0f1f9..f57b3204f19f3 100644 --- a/test/integration/next-image-new/app-dir/test/index.test.ts +++ b/test/integration/next-image-new/app-dir/test/index.test.ts @@ -358,12 +358,14 @@ function runTests(mode) { 'loaded 1 img9 with dimensions 400x400' ) - const warnings = (await browser.log('browser')) - .map((log) => log.message) - .join('\n') - expect(warnings).toMatch( - /Image with src "(.*)test(.*)jpg" is using deprecated "onLoadingComplete" property. Please use the "onLoad" property instead./gm - ) + if (mode === 'dev') { + const warnings = (await browser.log('browser')) + .map((log) => log.message) + .join('\n') + expect(warnings).toMatch( + /Image with src "(.*)" is using deprecated "onLoadingComplete" property/gm + ) + } }) it('should callback native onLoad with sythetic event', async () => { diff --git a/test/integration/next-image-new/default/test/index.test.ts b/test/integration/next-image-new/default/test/index.test.ts index ff39b4609ed6e..1de5c8271c94d 100644 --- a/test/integration/next-image-new/default/test/index.test.ts +++ b/test/integration/next-image-new/default/test/index.test.ts @@ -358,6 +358,15 @@ function runTests(mode) { () => browser.eval(`document.getElementById("msg9").textContent`), 'loaded 1 img9 with dimensions 400x400' ) + + if (mode === 'dev') { + const warnings = (await browser.log('browser')) + .map((log) => log.message) + .join('\n') + expect(warnings).toMatch( + /Image with src "(.*)" is using deprecated "onLoadingComplete" property/gm + ) + } }) it('should callback native onLoad with sythetic event', async () => {