Skip to content

Commit 35f6080

Browse files
samselikoffijjk
andauthored
Re-enable legacyBehavior and passHref on Link (#84500)
In #83003, `legacyBehavior` and `passHref` were removed from `<Link>`. However, this turned out to be a bit premature—despite most usage being covered by the newer `<Link>` APIs, there's some use cases we don't yet have good alternatives for. We expect to solve this with an API that uses Fragment Refs once they're available in React. For now, we're re-enabling these flags. --------- Co-authored-by: JJ Kasper <[email protected]>
1 parent 41e3942 commit 35f6080

File tree

52 files changed

+1547
-68
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1547
-68
lines changed

crates/next-core/src/next_import_map.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,7 @@ async fn apply_vendored_react_aliases_server(
983983
// This is used in the server runtime to import React Server Components.
984984
alias.extend(fxindexmap! {
985985
rcstr!("next/navigation") => rcstr!("next/dist/api/navigation.react-server"),
986+
rcstr!("next/link") => rcstr!("next/dist/client/app-dir/link.react-server"),
986987
});
987988
}
988989

@@ -1012,6 +1013,7 @@ async fn rsc_aliases(
10121013
// This is used in the server runtime to import React Server Components.
10131014
alias.extend(fxindexmap! {
10141015
rcstr!("next/navigation") => rcstr!("next/dist/api/navigation.react-server"),
1016+
rcstr!("next/link") => rcstr!("next/dist/client/app-dir/link.react-server"),
10151017
});
10161018
}
10171019

packages/next/errors.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -860,5 +860,6 @@
860860
"859": "An IO error occurred while attempting to create and acquire the lockfile",
861861
"860": "Client Max Body Size must be a valid number (bytes) or filesize format string (e.g., \"5mb\")",
862862
"861": "Client Max Body Size must be larger than 0 bytes",
863-
"862": "Request body exceeded %s"
863+
"862": "Request body exceeded %s",
864+
"863": "\\`<Link legacyBehavior>\\` received a direct child that is either a Server Component, or JSX that was loaded with React.lazy(). This is not supported. Either remove legacyBehavior, or make the direct child a Client Component that renders the Link's \\`<a>\\` tag."
864865
}

packages/next/src/build/create-compiler-aliases.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ export function createAppRouterApiAliases(isServerOnlyLayer: boolean) {
238238

239239
if (isServerOnlyLayer) {
240240
mapping['navigation'] = 'next/dist/api/navigation.react-server'
241+
mapping['link'] = 'next/dist/client/app-dir/link.react-server'
241242
}
242243

243244
const aliasMap: Record<string, string> = {}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import type { ComponentProps } from 'react'
2+
import ClientLinkComponent, { type LinkProps, useLinkStatus } from './link'
3+
4+
export default function LinkComponent(
5+
props: ComponentProps<typeof ClientLinkComponent>
6+
) {
7+
const isLegacyBehavior = props.legacyBehavior
8+
const childIsHostComponent =
9+
typeof props.children === 'string' ||
10+
typeof props.children === 'number' ||
11+
typeof (props.children as any)?.type === 'string'
12+
const childIsClientComponent =
13+
(props.children as any)?.type?.$$typeof ===
14+
Symbol.for('react.client.reference')
15+
16+
if (isLegacyBehavior && !childIsHostComponent && !childIsClientComponent) {
17+
if ((props.children as any)?.type?.$$typeof === Symbol.for('react.lazy')) {
18+
console.error(
19+
`Using a Lazy Component as a direct child of \`<Link legacyBehavior>\` from a Server Component is not supported. If you need legacyBehavior, wrap your Lazy Component in a Client Component that renders the Link's \`<a>\` tag.`
20+
)
21+
} else {
22+
console.error(
23+
`Using a Server Component as a direct child of \`<Link legacyBehavior>\` is not supported. If you need legacyBehavior, wrap your Server Component in a Client Component that renders the Link's \`<a>\` tag.`
24+
)
25+
}
26+
}
27+
28+
return <ClientLinkComponent {...props} />
29+
}
30+
31+
export { type LinkProps, useLinkStatus }

0 commit comments

Comments
 (0)