Skip to content

Commit

Permalink
chore(next/image)!: mark onLoadingComplete as deprecated in favor o…
Browse files Browse the repository at this point in the history
…f `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`.
  • Loading branch information
styfle authored Oct 17, 2023
1 parent 6ed4fdd commit 3a459ca
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 24 deletions.
44 changes: 23 additions & 21 deletions docs/02-app/02-api-reference/01-components/image.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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>

Expand Down Expand Up @@ -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.

Expand Down
2 changes: 1 addition & 1 deletion examples/with-cloudinary/components/SharedModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
2 changes: 1 addition & 1 deletion examples/with-sfcc/components/ProductCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down
12 changes: 11 additions & 1 deletion packages/next/src/shared/lib/get-img-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down Expand Up @@ -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.`
)
}

Expand All @@ -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,
Expand Down
9 changes: 9 additions & 0 deletions test/integration/next-image-new/app-dir/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down
9 changes: 9 additions & 0 deletions test/integration/next-image-new/default/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down

0 comments on commit 3a459ca

Please sign in to comment.