Skip to content

Commit 1e98f8b

Browse files
committed
docs: add warning for html/body tags causing infinite loop in React 19 (#8340)
1 parent 40ea071 commit 1e98f8b

File tree

1 file changed

+35
-0
lines changed

1 file changed

+35
-0
lines changed

src/content/blog/2024/04/25/react-19-upgrade-guide.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,41 @@ To load React 19 with a script tag, we recommend using an ESM-based CDN such as
563563
</script>
564564
```
565565

566+
### Support for Document Metadata {/*support-for-document-metadata*/}
567+
568+
React 19 added support for rendering metadata tags like `<title>`, `<meta>`, and `<link>` natively in your component tree, and they will automatically be hoisted to the document `<head>`.
569+
570+
<Pitfall>
571+
572+
#### `<html>` and `<body>` tags are not supported for hoisting {/*html-and-body-not-supported*/}
573+
574+
While React 19 hoists `<title>`, `<meta>`, and `<link>` tags automatically, it does **not** support rendering `<html>` or `<body>` tags inside a `createRoot` component tree.
575+
576+
If you are migrating from `react-helmet` and render `<html>` or `<body>` directly in JSX, this will cause a **terminal infinite loop** (browser freeze) during event propagation such as input focus.
577+
```js
578+
// 🚩 Do not do this — causes infinite loop
579+
function App() {
580+
return (
581+
<>
582+
<html lang="en" />
583+
<body className="dark" />
584+
<main>...</main>
585+
</>
586+
);
587+
}
588+
```
589+
590+
Instead, set attributes on `<html>` and `<body>` in your HTML file or server template:
591+
```html
592+
<html lang="en">
593+
<body class="dark">
594+
<div id="root"></div>
595+
</body>
596+
</html>
597+
```
598+
599+
</Pitfall>
600+
566601
### Libraries depending on React internals may block upgrades {/*libraries-depending-on-react-internals-may-block-upgrades*/}
567602

568603
This release includes changes to React internals that may impact libraries that ignore our pleas to not use internals like `SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED`. These changes are necessary to land improvements in React 19, and will not break libraries that follow our guidelines.

0 commit comments

Comments
 (0)