Skip to content

Commit b41497d

Browse files
fix(next/image): don't call ReactDOM.preload if missing, such as jest (#53443)
### What? `ReactDOM.preload` is available in `react-dom@experimental` builds. If it's not available, we should fall back to `Head`+`link` ### Why? Since `ReactDOM.preload` is only available in `react-dom@experimental` builds, certain environments (like Jest or [Storybook](storybookjs/storybook#23661)) might have a version of `react-dom` installed that won't work with `preload()` ### How? Closes NEXT-1482 Fixes #53272 See also: storybookjs/storybook#23661 Co-authored-by: Steven <[email protected]>
1 parent c669c38 commit b41497d

File tree

6 files changed

+87
-1
lines changed

6 files changed

+87
-1
lines changed

packages/next/src/client/image-component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ function ImagePreload({
320320
...getDynamicProps(imgAttributes.fetchPriority),
321321
}
322322

323-
if (isAppRouter) {
323+
if (isAppRouter && preload) {
324324
// See https://github.com/facebook/react/pull/26940
325325
preload(
326326
imgAttributes.src,
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import React from 'react'
2+
export default function RootLayout({
3+
children,
4+
}: {
5+
children: React.ReactNode
6+
}) {
7+
return (
8+
<html lang="en">
9+
<body>{children}</body>
10+
</html>
11+
)
12+
}
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import React from 'react'
2+
import Image from 'next/image'
3+
import logo from './next.svg'
4+
5+
export default function MyImage() {
6+
return <Image alt="" src={logo} priority />
7+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
const nextJest = require('next/jest')
2+
3+
const createJestConfig = nextJest({
4+
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
5+
dir: './',
6+
})
7+
8+
// Add any custom config to be passed to Jest
9+
const customJestConfig = {
10+
// if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
11+
moduleDirectories: ['node_modules', '<rootDir>/'],
12+
testEnvironment: 'jest-environment-jsdom',
13+
}
14+
15+
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
16+
module.exports = createJestConfig(customJestConfig)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { createNext, FileRef } from 'e2e-utils'
2+
import { NextInstance } from 'test/lib/next-modes/base'
3+
import path from 'path'
4+
import execa from 'execa'
5+
6+
const appDir = path.join(__dirname, 'app')
7+
8+
describe('next/jest', () => {
9+
let next: NextInstance
10+
11+
beforeAll(async () => {
12+
next = await createNext({
13+
skipStart: true,
14+
files: {
15+
app: new FileRef(path.join(appDir, 'app')),
16+
[`tests/index.test.tsx`]: `
17+
import { render, screen } from '@testing-library/react'
18+
import Page from '../app/page'
19+
20+
it('<Page /> renders', () => {
21+
render(<Page />)
22+
const logo = screen.getByRole('img')
23+
expect(logo).toBeDefined()
24+
})
25+
`,
26+
'jest.config.js': new FileRef(path.join(appDir, 'jest.config.js')),
27+
},
28+
dependencies: {
29+
jest: '29.6.2',
30+
'jest-environment-jsdom': '29.6.2',
31+
'@testing-library/react': '14.0.0',
32+
'@testing-library/jest-dom': '5.17.0',
33+
},
34+
})
35+
})
36+
afterAll(() => next.destroy())
37+
38+
it('Should not throw preload is undefined error', async () => {
39+
const { stdout, stderr } = await execa(
40+
'pnpm',
41+
['jest', 'tests/index.test.tsx'],
42+
{
43+
cwd: next.testDir,
44+
reject: false,
45+
}
46+
)
47+
// Uncaught [TypeError: (0 , _reactdom.preload) is not a function]
48+
expect(stdout + stderr).not.toContain('is not a function')
49+
})
50+
})

0 commit comments

Comments
 (0)