From 8a8df94129f1e830cd337c4aa619aa8b827697aa Mon Sep 17 00:00:00 2001 From: Steven Date: Mon, 24 Oct 2022 16:01:49 -0700 Subject: [PATCH 1/6] Throw error child in --- errors/manifest.json | 4 +++ errors/new-link-a-tag.md | 21 +++++++++++++ packages/next/client/link.tsx | 8 +++++ .../child-a-tag-error.test.ts | 30 +++++++++++++++++++ .../child-a-tag-error/next.config.js | 3 ++ .../child-a-tag-error/pages/index.js | 12 ++++++++ 6 files changed, 78 insertions(+) create mode 100644 errors/new-link-a-tag.md create mode 100644 test/e2e/new-link-behavior/child-a-tag-error.test.ts create mode 100644 test/e2e/new-link-behavior/child-a-tag-error/next.config.js create mode 100644 test/e2e/new-link-behavior/child-a-tag-error/pages/index.js diff --git a/errors/manifest.json b/errors/manifest.json index 79a55d1d71831d0..5b497f8fa067e71 100644 --- a/errors/manifest.json +++ b/errors/manifest.json @@ -694,6 +694,10 @@ "title": "nested-styled-jsx-tags", "path": "/errors/nested-styled-jsx-tags.md" }, + { + "title": "new-link-a-tag", + "path": "/errors/new-link-a-tag.md" + }, { "title": "returning-response-body-in-middleware", "path": "/errors/returning-response-body-in-middleware.md" diff --git a/errors/new-link-a-tag.md b/errors/new-link-a-tag.md new file mode 100644 index 000000000000000..ffd4a7a9894eb9a --- /dev/null +++ b/errors/new-link-a-tag.md @@ -0,0 +1,21 @@ +# Invalid with child + +#### Why This Error Occurred + +Starting with Next.js 13, `` renders as ``, so attempting to use `` as a child is invalid. + +#### Possible Ways to Fix It + +Run the `new-link` codemod to automatically upgrade previous versions of Next.js to the new `` usage: + +```sh +npx @next/codemod new-link . +``` + +This will change `Home` to `Home`. + +Alternatively, you can add the `legacyBehavior` prop `Home`. + +### Useful Links + +- [next/link](https://nextjs.org/docs/api-reference/next/link) diff --git a/packages/next/client/link.tsx b/packages/next/client/link.tsx index 5f89822900d42f5..58564bb6f726678 100644 --- a/packages/next/client/link.tsx +++ b/packages/next/client/link.tsx @@ -408,6 +408,14 @@ const Link = React.forwardRef( } else { child = React.Children.only(children) } + } else { + if (process.env.NODE_ENV === 'development') { + if ((children as any)?.type === 'a') { + throw new Error( + 'Invalid with child. Please remove or use .\nLearn more: https://nextjs.org/docs/messages/new-link-a-tag' + ) + } + } } const childRef: any = legacyBehavior diff --git a/test/e2e/new-link-behavior/child-a-tag-error.test.ts b/test/e2e/new-link-behavior/child-a-tag-error.test.ts new file mode 100644 index 000000000000000..631ef6ef5a2834c --- /dev/null +++ b/test/e2e/new-link-behavior/child-a-tag-error.test.ts @@ -0,0 +1,30 @@ +import { createNext, FileRef, hasRedbox } from 'e2e-utils' +import { NextInstance } from 'test/lib/next-modes/base' +import webdriver from 'next-webdriver' +import path from 'path' + +const appDir = path.join(__dirname, 'stitches') + +describe('New Link Behavior with child', () => { + let next: NextInstance + + beforeAll(async () => { + next = await createNext({ + files: { + pages: new FileRef(path.join(appDir, 'pages')), + 'next.config.js': new FileRef(path.join(appDir, 'next.config.js')), + }, + dependencies: { + next: 'latest', + react: 'latest', + 'react-dom': 'latest', + }, + }) + }) + afterAll(() => next.destroy()) + + it('should throw error with child', async () => { + const browser = await webdriver(next.url, `/`) + expect(await hasRedbox(browser, true)).toBe(true) + }) +}) diff --git a/test/e2e/new-link-behavior/child-a-tag-error/next.config.js b/test/e2e/new-link-behavior/child-a-tag-error/next.config.js new file mode 100644 index 000000000000000..0d6071006ab351f --- /dev/null +++ b/test/e2e/new-link-behavior/child-a-tag-error/next.config.js @@ -0,0 +1,3 @@ +module.exports = { + reactStrictMode: true, +} diff --git a/test/e2e/new-link-behavior/child-a-tag-error/pages/index.js b/test/e2e/new-link-behavior/child-a-tag-error/pages/index.js new file mode 100644 index 000000000000000..6c6ed7b5534dd34 --- /dev/null +++ b/test/e2e/new-link-behavior/child-a-tag-error/pages/index.js @@ -0,0 +1,12 @@ +import Link from 'next/link' + +export default function Page() { + return ( + <> +

Should Error with "a" tag

+ +
Home + + + ) +} From 4dd7a2cf73ef058d98e8ceee633e981afe27442e Mon Sep 17 00:00:00 2001 From: Steven Date: Mon, 24 Oct 2022 16:08:46 -0700 Subject: [PATCH 2/6] Fix assertion --- test/e2e/new-link-behavior/child-a-tag-error.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/e2e/new-link-behavior/child-a-tag-error.test.ts b/test/e2e/new-link-behavior/child-a-tag-error.test.ts index 631ef6ef5a2834c..9ff33ac945d25cd 100644 --- a/test/e2e/new-link-behavior/child-a-tag-error.test.ts +++ b/test/e2e/new-link-behavior/child-a-tag-error.test.ts @@ -1,4 +1,5 @@ -import { createNext, FileRef, hasRedbox } from 'e2e-utils' +import { createNext, FileRef } from 'e2e-utils' +import { getRedboxSource, hasRedbox } from 'next-test-utils' import { NextInstance } from 'test/lib/next-modes/base' import webdriver from 'next-webdriver' import path from 'path' @@ -26,5 +27,8 @@ describe('New Link Behavior with child', () => { it('should throw error with child', async () => { const browser = await webdriver(next.url, `/`) expect(await hasRedbox(browser, true)).toBe(true) + expect(await getRedboxSource(browser)).toContain( + 'Error: Invalid with child. Please remove or use ' + ) }) }) From b8911cb8ef948c7d62b1c927924daed28c2c7468 Mon Sep 17 00:00:00 2001 From: Steven Date: Mon, 24 Oct 2022 16:21:18 -0700 Subject: [PATCH 3/6] Check stderr and check for dev modal --- test/e2e/new-link-behavior/child-a-tag-error.test.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test/e2e/new-link-behavior/child-a-tag-error.test.ts b/test/e2e/new-link-behavior/child-a-tag-error.test.ts index 9ff33ac945d25cd..a90a604eb9419bd 100644 --- a/test/e2e/new-link-behavior/child-a-tag-error.test.ts +++ b/test/e2e/new-link-behavior/child-a-tag-error.test.ts @@ -25,10 +25,13 @@ describe('New Link Behavior with child', () => { afterAll(() => next.destroy()) it('should throw error with child', async () => { - const browser = await webdriver(next.url, `/`) - expect(await hasRedbox(browser, true)).toBe(true) - expect(await getRedboxSource(browser)).toContain( + const msg = 'Error: Invalid with child. Please remove or use ' - ) + expect(next.cliOutput).toContain(msg) + if ((global as any).isDev) { + const browser = await webdriver(next.url, `/`) + expect(await hasRedbox(browser, true)).toBe(true) + expect(await getRedboxSource(browser)).toContain(msg) + } }) }) From 32e7bd90596a718b74a56dd4d90bc258cbd05580 Mon Sep 17 00:00:00 2001 From: Steven Date: Mon, 24 Oct 2022 19:08:41 -0700 Subject: [PATCH 4/6] Fix tests --- test/e2e/new-link-behavior/child-a-tag-error.test.ts | 9 +++++++-- .../child-a-tag-error/pages/about.js | 12 ++++++++++++ .../child-a-tag-error/pages/index.js | 6 +++--- 3 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 test/e2e/new-link-behavior/child-a-tag-error/pages/about.js diff --git a/test/e2e/new-link-behavior/child-a-tag-error.test.ts b/test/e2e/new-link-behavior/child-a-tag-error.test.ts index a90a604eb9419bd..b96f4418691c2b3 100644 --- a/test/e2e/new-link-behavior/child-a-tag-error.test.ts +++ b/test/e2e/new-link-behavior/child-a-tag-error.test.ts @@ -4,7 +4,7 @@ import { NextInstance } from 'test/lib/next-modes/base' import webdriver from 'next-webdriver' import path from 'path' -const appDir = path.join(__dirname, 'stitches') +const appDir = path.join(__dirname, 'child-a-tag-error') describe('New Link Behavior with child', () => { let next: NextInstance @@ -25,13 +25,18 @@ describe('New Link Behavior with child', () => { afterAll(() => next.destroy()) it('should throw error with child', async () => { + const browser = await webdriver(next.url, `/`) + const link = await browser.elementsByCss('a[href="/about"]') const msg = 'Error: Invalid with child. Please remove or use ' expect(next.cliOutput).toContain(msg) + if ((global as any).isDev) { - const browser = await webdriver(next.url, `/`) expect(await hasRedbox(browser, true)).toBe(true) expect(await getRedboxSource(browser)).toContain(msg) + expect(link).not.toBeDefined() + } else { + expect(link).toBeDefined() } }) }) diff --git a/test/e2e/new-link-behavior/child-a-tag-error/pages/about.js b/test/e2e/new-link-behavior/child-a-tag-error/pages/about.js new file mode 100644 index 000000000000000..e3c4a9ffa5c5abe --- /dev/null +++ b/test/e2e/new-link-behavior/child-a-tag-error/pages/about.js @@ -0,0 +1,12 @@ +import Link from 'next/link' + +export default function Page() { + return ( + <> +

About Page

+ +
Home + + + ) +} diff --git a/test/e2e/new-link-behavior/child-a-tag-error/pages/index.js b/test/e2e/new-link-behavior/child-a-tag-error/pages/index.js index 6c6ed7b5534dd34..a12ba52a7b5eaed 100644 --- a/test/e2e/new-link-behavior/child-a-tag-error/pages/index.js +++ b/test/e2e/new-link-behavior/child-a-tag-error/pages/index.js @@ -3,9 +3,9 @@ import Link from 'next/link' export default function Page() { return ( <> -

Should Error with "a" tag

- - Home +

Home Page

+ + About ) From 83737e1d99e038a4d0a476e5d87aa8f70cefaef2 Mon Sep 17 00:00:00 2001 From: Steven Date: Mon, 24 Oct 2022 19:44:33 -0700 Subject: [PATCH 5/6] Fix tests for dev vs start --- test/e2e/new-link-behavior/child-a-tag-error.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/new-link-behavior/child-a-tag-error.test.ts b/test/e2e/new-link-behavior/child-a-tag-error.test.ts index b96f4418691c2b3..bce50f68b5055b7 100644 --- a/test/e2e/new-link-behavior/child-a-tag-error.test.ts +++ b/test/e2e/new-link-behavior/child-a-tag-error.test.ts @@ -29,9 +29,9 @@ describe('New Link Behavior with child', () => { const link = await browser.elementsByCss('a[href="/about"]') const msg = 'Error: Invalid with child. Please remove or use ' - expect(next.cliOutput).toContain(msg) if ((global as any).isDev) { + expect(next.cliOutput).toContain(msg) expect(await hasRedbox(browser, true)).toBe(true) expect(await getRedboxSource(browser)).toContain(msg) expect(link).not.toBeDefined() From 5d70210e9aafa05a84632241a6fd2c92d4a0fda1 Mon Sep 17 00:00:00 2001 From: Steven Date: Mon, 24 Oct 2022 19:51:26 -0700 Subject: [PATCH 6/6] Rename to "invalid-new-link-with-extra-anchor" --- ...ew-link-a-tag.md => invalid-new-link-with-extra-anchor.md} | 0 errors/manifest.json | 4 ++-- packages/next/client/link.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename errors/{new-link-a-tag.md => invalid-new-link-with-extra-anchor.md} (100%) diff --git a/errors/new-link-a-tag.md b/errors/invalid-new-link-with-extra-anchor.md similarity index 100% rename from errors/new-link-a-tag.md rename to errors/invalid-new-link-with-extra-anchor.md diff --git a/errors/manifest.json b/errors/manifest.json index 5b497f8fa067e71..3b8e2ba093e719e 100644 --- a/errors/manifest.json +++ b/errors/manifest.json @@ -695,8 +695,8 @@ "path": "/errors/nested-styled-jsx-tags.md" }, { - "title": "new-link-a-tag", - "path": "/errors/new-link-a-tag.md" + "title": "invalid-new-link-with-extra-anchor", + "path": "/errors/invalid-new-link-with-extra-anchor.md" }, { "title": "returning-response-body-in-middleware", diff --git a/packages/next/client/link.tsx b/packages/next/client/link.tsx index 58564bb6f726678..3772932122e5dd4 100644 --- a/packages/next/client/link.tsx +++ b/packages/next/client/link.tsx @@ -412,7 +412,7 @@ const Link = React.forwardRef( if (process.env.NODE_ENV === 'development') { if ((children as any)?.type === 'a') { throw new Error( - 'Invalid with child. Please remove or use .\nLearn more: https://nextjs.org/docs/messages/new-link-a-tag' + 'Invalid with child. Please remove or use .\nLearn more: https://nextjs.org/docs/messages/invalid-new-link-with-extra-anchor' ) } }