Skip to content

Commit 1ee500b

Browse files
authored
[test] Use React 19.1 everywhere (#77895)
1 parent 920b48d commit 1ee500b

File tree

9 files changed

+58
-43
lines changed

9 files changed

+58
-43
lines changed

examples/reproduction-template/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
},
88
"dependencies": {
99
"next": "canary",
10-
"react": "^19.0.0",
11-
"react-dom": "^19.0.0"
10+
"react": "19.1.0",
11+
"react-dom": "19.1.0"
1212
},
1313
"devDependencies": {
1414
"@types/node": "^22",

packages/create-next-app/templates/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { GetTemplateFileArgs, InstallTemplateArgs } from "./types";
1313

1414
// Do not rename or format. sync-react script relies on this line.
1515
// prettier-ignore
16-
const nextjsReactPeerVersion = "^19.0.0";
16+
const nextjsReactPeerVersion = "19.1.0";
1717

1818
/**
1919
* Get the file path for a given file in a template, e.g. "next.config.js".

run-tests.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const { getTestFilter } = require('./test/get-test-filter')
1919

2020
// Do not rename or format. sync-react script relies on this line.
2121
// prettier-ignore
22-
const nextjsReactPeerVersion = "^19.0.0";
22+
const nextjsReactPeerVersion = "19.1.0";
2323

2424
let argv = require('yargs/yargs')(process.argv.slice(2))
2525
.string('type')

scripts/sync-react.js

Lines changed: 47 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const fsp = require('fs/promises')
55
const process = require('process')
66
const execa = require('execa')
77
const { Octokit } = require('octokit')
8+
const SemVer = require('semver')
89
const yargs = require('yargs')
910

1011
/** @type {any} */
@@ -17,9 +18,13 @@ const pullRequestReviewers = ['eps1lon']
1718
/**
1819
* Set to `null` to automatically sync the React version of Pages Router with App Router React version.
1920
* Set to a specific version to override the Pages Router React version e.g. `^19.0.0`.
21+
*
22+
* "Active" just refers to our current development practice. While we do support
23+
* React 18 in pages router, we don't focus our development process on it considering
24+
* it does not receive new features.
2025
* @type {string | null}
2126
*/
22-
const pagesRouterReact = '^19.0.0'
27+
const activePagesRouterReact = '^19.0.0'
2328

2429
const defaultLatestChannel = 'canary'
2530
const filesReferencingReactPeerDependencyVersion = [
@@ -176,6 +181,31 @@ async function getChangelogFromGitHub(baseSha, newSha) {
176181
return changelog.length > 0 ? changelog.join('\n') : null
177182
}
178183

184+
async function findHighestNPMReactVersion(versionLike) {
185+
const { stdout, stderr } = await execa(
186+
'npm',
187+
['--silent', 'view', '--json', `react@${versionLike}`, 'version'],
188+
{
189+
// Avoid "Usage Error: This project is configured to use pnpm".
190+
cwd: '/tmp',
191+
}
192+
)
193+
if (stderr) {
194+
console.error(stderr)
195+
throw new Error(
196+
`Failed to read highest react@${versionLike} version from npm.`
197+
)
198+
}
199+
200+
const result = JSON.parse(stdout)
201+
202+
return typeof result === 'string'
203+
? result
204+
: result.sort((a, b) => {
205+
return SemVer.compare(b, a)
206+
})[0]
207+
}
208+
179209
async function main() {
180210
const cwd = process.cwd()
181211
const errors = []
@@ -232,19 +262,7 @@ async function main() {
232262
// TODO: Fork arguments in GitHub workflow to ensure `--version ""` is considered a mistake
233263
newVersionStr === ''
234264
) {
235-
const { stdout, stderr } = await execa(
236-
'npm',
237-
['--silent', 'view', `react@${defaultLatestChannel}`, 'version'],
238-
{
239-
// Avoid "Usage Error: This project is configured to use pnpm".
240-
cwd: '/tmp',
241-
}
242-
)
243-
if (stderr) {
244-
console.error(stderr)
245-
throw new Error('Failed to read latest React canary version from npm.')
246-
}
247-
newVersionStr = stdout.trim()
265+
newVersionStr = await findHighestNPMReactVersion(defaultLatestChannel)
248266
console.log(
249267
`--version was not provided. Using react@${defaultLatestChannel}: ${newVersionStr}`
250268
)
@@ -325,24 +343,28 @@ Or, run this command with no arguments to use the most recently published versio
325343
)
326344
}
327345

328-
const syncPagesRouterReact = pagesRouterReact === null
329-
const pagesRouterReactVersion = syncPagesRouterReact
346+
const syncPagesRouterReact = activePagesRouterReact === null
347+
const newActivePagesRouterReactVersion = syncPagesRouterReact
330348
? newVersionStr
331-
: pagesRouterReact
349+
: activePagesRouterReact
350+
const pagesRouterReactVersion = `^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ${newActivePagesRouterReactVersion}`
351+
const highestPagesRouterReactVersion = await findHighestNPMReactVersion(
352+
pagesRouterReactVersion
353+
)
332354
const { sha: baseSha, dateString: baseDateString } = baseVersionInfo
333355

334356
if (syncPagesRouterReact) {
335357
for (const fileName of filesReferencingReactPeerDependencyVersion) {
336358
const filePath = path.join(cwd, fileName)
337359
const previousSource = await fsp.readFile(filePath, 'utf-8')
338360
const updatedSource = previousSource.replace(
339-
`const nextjsReactPeerVersion = "${baseVersionStr}";`,
340-
`const nextjsReactPeerVersion = "${pagesRouterReactVersion}";`
361+
/const nextjsReactPeerVersion = "[^"]+";/,
362+
`const nextjsReactPeerVersion = "${highestPagesRouterReactVersion}";`
341363
)
342-
if (pagesRouterReact === null && updatedSource === previousSource) {
364+
if (activePagesRouterReact === null && updatedSource === previousSource) {
343365
errors.push(
344366
new Error(
345-
`${fileName}: Failed to update ${baseVersionStr} to ${pagesRouterReactVersion}. Is this file still referencing the React peer dependency version?`
367+
`${fileName}: Failed to update ${baseVersionStr} to ${highestPagesRouterReactVersion}. Is this file still referencing the React peer dependency version?`
346368
)
347369
)
348370
} else {
@@ -356,10 +378,10 @@ Or, run this command with no arguments to use the most recently published versio
356378
const packageJson = await fsp.readFile(packageJsonPath, 'utf-8')
357379
const manifest = JSON.parse(packageJson)
358380
if (manifest.dependencies['react']) {
359-
manifest.dependencies['react'] = pagesRouterReactVersion
381+
manifest.dependencies['react'] = highestPagesRouterReactVersion
360382
}
361383
if (manifest.dependencies['react-dom']) {
362-
manifest.dependencies['react-dom'] = pagesRouterReactVersion
384+
manifest.dependencies['react-dom'] = highestPagesRouterReactVersion
363385
}
364386
await fsp.writeFile(
365387
packageJsonPath,
@@ -379,12 +401,10 @@ Or, run this command with no arguments to use the most recently published versio
379401
const manifest = JSON.parse(packageJson)
380402
// Need to specify last supported RC version to avoid breaking changes.
381403
if (manifest.peerDependencies['react']) {
382-
manifest.peerDependencies['react'] =
383-
`^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ${pagesRouterReactVersion}`
404+
manifest.peerDependencies['react'] = pagesRouterReactVersion
384405
}
385406
if (manifest.peerDependencies['react-dom']) {
386-
manifest.peerDependencies['react-dom'] =
387-
`^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ${pagesRouterReactVersion}`
407+
manifest.peerDependencies['react-dom'] = pagesRouterReactVersion
388408
}
389409
await fsp.writeFile(
390410
packageJsonPath,

test/.stats-app/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
"license": "MIT",
55
"dependencies": {
66
"next": "latest",
7-
"react": "^19.0.0",
8-
"react-dom": "^19.0.0"
7+
"react": "19.1.0",
8+
"react-dom": "19.1.0"
99
},
1010
"engines": {
1111
"node": ">=18.18.0"

test/development/acceptance/hydration-error.test.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,6 @@ describe('Error overlay for hydration errors in Pages router', () => {
1111
const { next } = nextTestSetup({
1212
files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')),
1313
skipStart: true,
14-
// TODO: once Next.js minimal React version is 19.1, remove this override.
15-
dependencies: {
16-
react: isReact18 ? '^18.3.1' : '^19.1.0',
17-
'react-dom': isReact18 ? '^18.3.1' : '^19.1.0',
18-
},
1914
})
2015

2116
it('includes a React docs link when hydration error does occur', async () => {

test/e2e/next-test/first-time-setup-js/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
},
99
"dependencies": {
1010
"next": "canary",
11-
"react": "^19.0.0",
12-
"react-dom": "^19.0.0"
11+
"react": "19.1.0",
12+
"react-dom": "19.1.0"
1313
}
1414
}

test/e2e/next-test/first-time-setup-ts/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
},
99
"dependencies": {
1010
"next": "canary",
11-
"react": "^19.0.0",
12-
"react-dom": "^19.0.0"
11+
"react": "19.1.0",
12+
"react-dom": "19.1.0"
1313
},
1414
"devDependencies": {
1515
"@types/react": "^18",

test/lib/next-modes/base.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ type OmitFirstArgument<F> = F extends (
5858

5959
// Do not rename or format. sync-react script relies on this line.
6060
// prettier-ignore
61-
const nextjsReactPeerVersion = "^19.0.0";
61+
const nextjsReactPeerVersion = "19.1.0";
6262

6363
export class NextInstance {
6464
protected files: ResolvedFileConfig

0 commit comments

Comments
 (0)