diff --git a/packages/next/src/client/components/app-router-announcer.tsx b/packages/next/src/client/components/app-router-announcer.tsx index 7339498953aa3..b804e72d90add 100644 --- a/packages/next/src/client/components/app-router-announcer.tsx +++ b/packages/next/src/client/components/app-router-announcer.tsx @@ -57,7 +57,10 @@ export function AppRouterAnnouncer({ tree }: { tree: FlightRouterState }) { // Only announce the title change, but not for the first load because screen // readers do that automatically. - if (previousTitle.current !== undefined) { + if ( + previousTitle.current !== undefined && + previousTitle.current !== currentTitle + ) { setRouteAnnouncement(currentTitle) } previousTitle.current = currentTitle diff --git a/packages/next/src/server/config-schema.ts b/packages/next/src/server/config-schema.ts index 49dbc1a53de19..d51ee7c759595 100644 --- a/packages/next/src/server/config-schema.ts +++ b/packages/next/src/server/config-schema.ts @@ -748,6 +748,7 @@ const configSchema = { }, reactStrictMode: { type: 'boolean', + nullable: true, }, redirects: { isFunction: true, diff --git a/packages/next/src/server/config-shared.ts b/packages/next/src/server/config-shared.ts index 0be5639f1ae89..cdbc25860d143 100644 --- a/packages/next/src/server/config-shared.ts +++ b/packages/next/src/server/config-shared.ts @@ -682,7 +682,7 @@ export const defaultConfig: NextConfig = { serverRuntimeConfig: {}, publicRuntimeConfig: {}, reactProductionProfiling: false, - reactStrictMode: false, + reactStrictMode: null, httpAgentOptions: { keepAlive: true, }, diff --git a/test/development/app-dir/strict-mode-enabled-by-default/app/layout.js b/test/development/app-dir/strict-mode-enabled-by-default/app/layout.js new file mode 100644 index 0000000000000..a3a86a5ca1e12 --- /dev/null +++ b/test/development/app-dir/strict-mode-enabled-by-default/app/layout.js @@ -0,0 +1,7 @@ +export default function Root({ children }) { + return ( + + {children} + + ) +} diff --git a/test/development/app-dir/strict-mode-enabled-by-default/app/page.js b/test/development/app-dir/strict-mode-enabled-by-default/app/page.js new file mode 100644 index 0000000000000..e39b8a8c7a6d9 --- /dev/null +++ b/test/development/app-dir/strict-mode-enabled-by-default/app/page.js @@ -0,0 +1,9 @@ +'use client' +import { useEffect } from 'react' + +let i = 1 +export default function Page() { + useEffect(() => { + console.log(`logged ${i++} times`) + }, []) +} diff --git a/test/development/app-dir/strict-mode-enabled-by-default/strict-mode-enabled-by-default.test.ts b/test/development/app-dir/strict-mode-enabled-by-default/strict-mode-enabled-by-default.test.ts new file mode 100644 index 0000000000000..cf3c6240e3f06 --- /dev/null +++ b/test/development/app-dir/strict-mode-enabled-by-default/strict-mode-enabled-by-default.test.ts @@ -0,0 +1,23 @@ +import { createNextDescribe } from 'e2e-utils' +import { BrowserInterface } from 'test/lib/browsers/base' + +createNextDescribe( + 'Strict Mode enabled by default', + { + files: __dirname, + }, + ({ next }) => { + // Recommended for tests that need a full browser + it('should work using browser', async () => { + const browser: BrowserInterface = await next.browser('/') + const logs = await browser.log() + const userLogs = logs.filter( + (log) => log.source === 'log' && log.message.match(/logged \d times/) + ) + expect(userLogs.length).toBe(2) + userLogs.forEach((log, i) => { + expect(log.message).toBe(`logged ${i + 1} times`) + }) + }) + } +)