chore(next/image)!: mark onLoadingComplete as deprecated in favor of onLoad (#56944)

## History

We used to pass `onLoad` through directly to the underlying img so `onLoadingComplete` was introduced in order to handle the case when `placeholder="blur"` was used and `onLoad` would trigger before the placeholder was removed.

We have since changed the behavior of `onLoad` so that it acts the same as `onLoadingComplete` and therefore `onLoadingComplete` is no longer needed.

## What is this PR doing?

This PR marks `onLoadingComplete` as deprecated in favor of `onLoad`. In the future, we may remove `onLoadingComplete`.
This commit is contained in:
Steven 2023-10-17 17:12:22 -04:00 committed by GitHub
parent 6ed4fddf8a
commit 3a459ca986
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 54 additions and 24 deletions

View file

@ -40,24 +40,24 @@ export default function Page() {
Here's a summary of the props available for the Image Component:
<div style={{ overflowX: 'auto', width: '100%' }}>
| 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 | - |
</div>
## Required Props
@ -286,6 +286,8 @@ Remember that the required width and height props can interact with your styling
<Image onLoadingComplete={(img) => 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 `<img>` element.
@ -302,9 +304,9 @@ The callback function will be called with one argument, a reference to the under
<Image onLoad={(e) => 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 `<img>` element.
<AppOnly>
@ -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.

View file

@ -81,7 +81,7 @@ export default function SharedModal({
height={navigation ? 853 : 1280}
priority
alt="Next.js Conf image"
onLoadingComplete={() => setLoaded(true)}
onLoad={() => setLoaded(true)}
/>
</motion.div>
</AnimatePresence>

View file

@ -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)}
/>
</div>
<div className="mt-4 flex items-center justify-between text-base font-medium text-gray-900">

View file

@ -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,

View file

@ -357,6 +357,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 () => {

View file

@ -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 () => {