Skip to content

Commit

Permalink
fix: handle different cases of React fetchPriority (#47302)
Browse files Browse the repository at this point in the history
In React 18.3.0 or newer, we must user camelCase `fetchPriority` prop to avoid "Warning: Invalid DOM property".

In React 18.2.0 and older, we must use the lowercase `fetchpriority` prop to avoid "Warning: Invalid DOM property".

See facebook/react#25927
  • Loading branch information
styfle authored Mar 20, 2023
1 parent 23c9f0e commit 7cc4159
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 4 deletions.
24 changes: 20 additions & 4 deletions packages/next/src/client/image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import React, {
useMemo,
useState,
forwardRef,
version,
} from 'react'
import Head from '../shared/lib/head'
import { getImageBlurSvg } from '../shared/lib/image-blur-svg'
Expand Down Expand Up @@ -367,6 +368,23 @@ function handleLoading(
})
}

function getDynamicProps(
fetchPriority?: string
): Record<string, string | undefined> {
const [majorStr, minorStr] = version.split('.')
const major = parseInt(majorStr, 10)
const minor = parseInt(minorStr, 10)
if (major > 18 || (major === 18 && minor >= 3)) {
// In React 18.3.0 or newer, we must use camelCase
// prop to avoid "Warning: Invalid DOM property".
// See https://github.com/facebook/react/pull/25927
return { fetchPriority }
}
// In React 18.2.0 or older, we must use lowercase prop
// to avoid "Warning: Invalid DOM property".
return { fetchpriority: fetchPriority }
}

const ImageElement = forwardRef<HTMLImageElement | null, ImageElementProps>(
(
{
Expand Down Expand Up @@ -401,10 +419,9 @@ const ImageElement = forwardRef<HTMLImageElement | null, ImageElementProps>(
<>
<img
{...rest}
{...getDynamicProps(fetchPriority)}
// @ts-expect-error - TODO: upgrade to `@types/react@18`
loading={loading}
// Keep lowercase until https://github.com/facebook/react/pull/25927 lands
fetchpriority={fetchPriority}
width={widthInt}
height={heightInt}
decoding="async"
Expand Down Expand Up @@ -959,8 +976,7 @@ const Image = forwardRef<HTMLImageElement | null, ImageProps>(
imageSrcSet={imgAttributes.srcSet}
imageSizes={imgAttributes.sizes}
crossOrigin={rest.crossOrigin}
// Keep lowercase until https://github.com/facebook/react/pull/25927 lands
fetchpriority={fetchPriority}
{...getDynamicProps(fetchPriority)}
/>
</Head>
) : null}
Expand Down
6 changes: 6 additions & 0 deletions test/integration/next-image-new/default/pages/priority.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ const Page = () => {
<Image
priority
id="basic-image"
alt="basic-image"
src="/test.jpg"
width="400"
height="400"
></Image>
<Image
priority
id="basic-image-crossorigin"
alt="basic-image-crossorigin"
src="/test.jpg"
width="400"
height="400"
Expand All @@ -23,13 +25,15 @@ const Page = () => {
<Image
loading="eager"
id="load-eager"
alt="load-eager"
src="/test.png"
width="400"
height="400"
></Image>
<Image
priority
id="responsive1"
alt="responsive1"
src="/wide.png"
width="1200"
height="700"
Expand All @@ -38,13 +42,15 @@ const Page = () => {
<Image
priority
id="responsive2"
alt="responsive2"
src="/wide.png"
width="1200"
height="700"
sizes="100vw"
/>
<Image
id="pri-low"
alt="pri-low"
src="/test.webp"
width="100"
height="100"
Expand Down
1 change: 1 addition & 0 deletions test/integration/next-image-new/default/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ function runTests(mode) {
expect(warnings).not.toMatch(
/was detected as the Largest Contentful Paint/gm
)
expect(warnings).not.toMatch(/React does not recognize the (.+) prop/gm)

// should preload with crossorigin
expect(
Expand Down

0 comments on commit 7cc4159

Please sign in to comment.