From 6d3924ef42a79f9a799914eb4caa448b046aee1e Mon Sep 17 00:00:00 2001 From: Yogayata Verma Date: Wed, 15 Apr 2026 15:24:39 +0530 Subject: [PATCH 1/8] docs(react-dom): add hydrateRoot hydration mismatch debugging guide --- .../reference/react-dom/client/hydrateRoot.md | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md index c48b6eb5196..c026fe1f8be 100644 --- a/src/content/reference/react-dom/client/hydrateRoot.md +++ b/src/content/reference/react-dom/client/hydrateRoot.md @@ -191,6 +191,7 @@ This is important for the user experience. The user will spend some time looking The most common causes leading to hydration errors include: * Extra whitespace (like newlines) around the React-generated HTML inside the root node. +* Using non-deterministic values like `Date.now()` or `Math.random()` in rendering logic. * Using checks like `typeof window !== 'undefined'` in your rendering logic. * Using browser-only APIs like [`window.matchMedia`](https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia) in your rendering logic. * Rendering different data on the server and the client. @@ -531,3 +532,42 @@ root.render(App, {onUncaughtError}); // ✅ Correct: pass options to createRoot. const root = hydrateRoot(container, , {onUncaughtError}); ``` + +### Debugging hydration mismatches {/*debugging-hydration-mismatches*/} + +If you see an error like "Hydration failed because the server rendered HTML didn't match the client.", it means the HTML from the server is different from what React renders first in the browser. + + + +Uncaught Error: Hydration failed because the server rendered HTML didn't match the client. + + + +#### Common causes {/*common-causes*/} + +* Values that change every time you render, like `Math.random()` or `Date.now()`. +* Rendering that depends on browser-only globals like `window`, `document`, or `localStorage`. +* Different data on the server and the client during the first render. +* Data loading timing issues where server data and client data do not match. + +#### Example mismatch {/*example-mismatch*/} + +```js +function App() { + return
{Math.random()}
; +} +``` + +This renders a different value on the server and the client, so hydration fails. + +#### Debugging checklist {/*debugging-checklist*/} + +1. Open the browser console and find the first hydration warning. +2. Look for changing values in render (`Math.random()`, `Date.now()`). Move them to server data or calculate them after hydration in [`useEffect`.](/reference/react/useEffect) +3. Keep browser-only code out of render. Read `window`, `document`, and similar APIs in [`useEffect`](/reference/react/useEffect) or an event handler. +4. Make sure the first client render uses the same data as the server render. +5. If one mismatch is expected (for example, a timestamp), use `suppressHydrationWarning={true}` on that element. + +#### Isolating the component {/*isolating-the-component*/} + +If you still cannot find the issue, replace parts of the UI with simple static markup. Add components back one at a time until the warning comes back. The last part you added is usually where the mismatch is. From e4385c4ded301450b7d102a148989631f5e192a9 Mon Sep 17 00:00:00 2001 From: Yogayata Verma Date: Wed, 15 Apr 2026 15:43:59 +0530 Subject: [PATCH 2/8] docs(react-dom): mark intentional Math.random example with expectedErrors to fix markdown code-block lint failure --- src/content/reference/react-dom/client/hydrateRoot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md index c026fe1f8be..ba055e77432 100644 --- a/src/content/reference/react-dom/client/hydrateRoot.md +++ b/src/content/reference/react-dom/client/hydrateRoot.md @@ -552,7 +552,7 @@ Uncaught Error: Hydration failed because the server rendered HTML didn't match t #### Example mismatch {/*example-mismatch*/} -```js +```js {expectedErrors: {'react-compiler': [2]}} function App() { return
{Math.random()}
; } From e74f0c81c6f8e564c6f4efc664ca2b2673f3ac34 Mon Sep 17 00:00:00 2001 From: Yogayata Verma Date: Wed, 15 Apr 2026 15:46:04 +0530 Subject: [PATCH 3/8] docs(react-dom): clarify hydrateRoot checklist to reference hydration mismatch error and stack trace --- src/content/reference/react-dom/client/hydrateRoot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md index ba055e77432..3650963784f 100644 --- a/src/content/reference/react-dom/client/hydrateRoot.md +++ b/src/content/reference/react-dom/client/hydrateRoot.md @@ -562,7 +562,7 @@ This renders a different value on the server and the client, so hydration fails. #### Debugging checklist {/*debugging-checklist*/} -1. Open the browser console and find the first hydration warning. +1. Open the browser console and find the hydration mismatch message or error, and its stack trace. 2. Look for changing values in render (`Math.random()`, `Date.now()`). Move them to server data or calculate them after hydration in [`useEffect`.](/reference/react/useEffect) 3. Keep browser-only code out of render. Read `window`, `document`, and similar APIs in [`useEffect`](/reference/react/useEffect) or an event handler. 4. Make sure the first client render uses the same data as the server render. From 92948647682efaf53e3ede3218a669130bdc7321 Mon Sep 17 00:00:00 2001 From: YOGAYATA VERMA <63913693+yogayataverma@users.noreply.github.com> Date: Wed, 15 Apr 2026 15:46:45 +0530 Subject: [PATCH 4/8] Update src/content/reference/react-dom/client/hydrateRoot.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/content/reference/react-dom/client/hydrateRoot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md index 3650963784f..ec1e47d0eeb 100644 --- a/src/content/reference/react-dom/client/hydrateRoot.md +++ b/src/content/reference/react-dom/client/hydrateRoot.md @@ -563,7 +563,7 @@ This renders a different value on the server and the client, so hydration fails. #### Debugging checklist {/*debugging-checklist*/} 1. Open the browser console and find the hydration mismatch message or error, and its stack trace. -2. Look for changing values in render (`Math.random()`, `Date.now()`). Move them to server data or calculate them after hydration in [`useEffect`.](/reference/react/useEffect) +2. Look for changing values in render (`Math.random()`, `Date.now()`). Move them to server data or calculate them after hydration in [`useEffect`](/reference/react/useEffect). 3. Keep browser-only code out of render. Read `window`, `document`, and similar APIs in [`useEffect`](/reference/react/useEffect) or an event handler. 4. Make sure the first client render uses the same data as the server render. 5. If one mismatch is expected (for example, a timestamp), use `suppressHydrationWarning={true}` on that element. From 636e68f3e3c3b70d4a0a5f777c3f6c277b3a7002 Mon Sep 17 00:00:00 2001 From: Yogayata Verma Date: Sun, 26 Apr 2026 16:23:42 +0530 Subject: [PATCH 5/8] docs(react-dom): clarify hydration mismatch guidance and remove incorrect expectedErrors annotation --- src/content/reference/react-dom/client/hydrateRoot.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md index ec1e47d0eeb..31ff15b2c79 100644 --- a/src/content/reference/react-dom/client/hydrateRoot.md +++ b/src/content/reference/react-dom/client/hydrateRoot.md @@ -552,7 +552,7 @@ Uncaught Error: Hydration failed because the server rendered HTML didn't match t #### Example mismatch {/*example-mismatch*/} -```js {expectedErrors: {'react-compiler': [2]}} +```js function App() { return
{Math.random()}
; } @@ -566,7 +566,7 @@ This renders a different value on the server and the client, so hydration fails. 2. Look for changing values in render (`Math.random()`, `Date.now()`). Move them to server data or calculate them after hydration in [`useEffect`](/reference/react/useEffect). 3. Keep browser-only code out of render. Read `window`, `document`, and similar APIs in [`useEffect`](/reference/react/useEffect) or an event handler. 4. Make sure the first client render uses the same data as the server render. -5. If one mismatch is expected (for example, a timestamp), use `suppressHydrationWarning={true}` on that element. +5. If a mismatch is truly unavoidable, such as a one-off timestamp, use `suppressHydrationWarning={true}` as a last resort on the specific element. Apply it narrowly and avoid using it on large subtrees because it only silences the warning and does not fix the mismatch. #### Isolating the component {/*isolating-the-component*/} From e651256d7fda3f6a4d4200ea7085049df061acb6 Mon Sep 17 00:00:00 2001 From: Yogayata Verma Date: Sun, 26 Apr 2026 16:29:29 +0530 Subject: [PATCH 6/8] docs(react-dom): add expected error annotation for Math.random hydration example --- src/content/reference/react-dom/client/hydrateRoot.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md index 31ff15b2c79..1fb8249eba6 100644 --- a/src/content/reference/react-dom/client/hydrateRoot.md +++ b/src/content/reference/react-dom/client/hydrateRoot.md @@ -552,11 +552,10 @@ Uncaught Error: Hydration failed because the server rendered HTML didn't match t #### Example mismatch {/*example-mismatch*/} -```js +```js {expectedErrors: {'react-compiler': [2]}} function App() { return
{Math.random()}
; } -``` This renders a different value on the server and the client, so hydration fails. From e3bce84b45a2e6e93ce7c5bbb5a7ace46dc53304 Mon Sep 17 00:00:00 2001 From: Yogayata Verma Date: Sun, 26 Apr 2026 16:32:52 +0530 Subject: [PATCH 7/8] docs(react-dom): avoid compiler annotation for hydration mismatch example --- src/content/reference/react-dom/client/hydrateRoot.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md index 1fb8249eba6..216b4c8a15e 100644 --- a/src/content/reference/react-dom/client/hydrateRoot.md +++ b/src/content/reference/react-dom/client/hydrateRoot.md @@ -552,10 +552,12 @@ Uncaught Error: Hydration failed because the server rendered HTML didn't match t #### Example mismatch {/*example-mismatch*/} -```js {expectedErrors: {'react-compiler': [2]}} +```jsx function App() { - return
{Math.random()}
; + const value = Math.random(); + return
{value}
; } +``` This renders a different value on the server and the client, so hydration fails. From 9e61292a75a30cda3e4503e85f447f67a4c96214 Mon Sep 17 00:00:00 2001 From: Yogayata Verma Date: Sun, 26 Apr 2026 16:36:36 +0530 Subject: [PATCH 8/8] docs(react-dom): avoid linting hydration mismatch example --- src/content/reference/react-dom/client/hydrateRoot.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md index 216b4c8a15e..24da4c605d0 100644 --- a/src/content/reference/react-dom/client/hydrateRoot.md +++ b/src/content/reference/react-dom/client/hydrateRoot.md @@ -552,10 +552,9 @@ Uncaught Error: Hydration failed because the server rendered HTML didn't match t #### Example mismatch {/*example-mismatch*/} -```jsx +```text function App() { - const value = Math.random(); - return
{value}
; + return
{Math.random()}
; } ```