audit-suppress-hydration-warning is the suppressHydrationWarning ESLint
check: it reports the attribute where it does nothing or hides more than you
meant, on an element with child elements, on static content, or on a
component. With the strict preset it reports every use, so each one needs a
comment that explains it.
| Rule | hydration-proof/audit-suppress-hydration-warning |
|---|---|
| What it reports | Report suppressHydrationWarning where it has no effect or hides more than intended |
| recommended / next | Error |
| strict | Error |
| Server Components | Checked (the markup is the same on both sides) |
| Suggestions | Yes |
| Options | allowOn, reportAll |
What the suppressHydrationWarning ESLint rule reports
suppressHydrationWarning (not ={false}) on:
- an HTML element with element children (
tooDeep). The attribute only covers the element's own attributes and its direct text, one level deep. A mismatch inside a child is still an error. - an HTML element whose attributes and text are all static (
unused). Nothing can differ, so the attribute only hides future mistakes.key,refand event handlers are ignored when deciding. A suggestion removes the attribute. - a component (
onComponent), such as<Clock suppressHydrationWarning />. It has no effect unless the component passes the prop to an HTML element. - with
reportAll: true(thestrictpreset), every other use (audit), so each suppression needs aneslint-disablecomment that explains it.
<html> and <body> are accepted by default (option allowOn): theme
scripts and browser extensions change their attributes before React hydrates,
which is the use case the attribute exists for.
Unlike most rules, this rule also checks
Server Components: the root layout, where
<html suppressHydrationWarning> usually lives, is one.
Why
suppressHydrationWarning tells React to keep the server's text and
attributes for one element without reporting a difference. Used in the wrong
place it either does nothing (the error still happens) or hides a real bug:
<div suppressHydrationWarning>
<span>{new Date().toLocaleTimeString()}</span>{" "}
{/* still a hydration error: the text is in the span */}
</div>hydration-proof test lists every difference hidden by the attribute as
HP6xxx info (HP6001 to HP6003),
so you can check what each one suppresses.
When suppressHydrationWarning is safe
covers the cases where the attribute is the right tool.
Incorrect
function Clock() {
return (
<div suppressHydrationWarning>
<span>{new Date().toLocaleTimeString("en-US", { timeZone: "UTC" })}</span>
</div>
);
}
function Title() {
return <h1 suppressHydrationWarning>Dashboard</h1>;
}
function Page() {
return <RelativeTime suppressHydrationWarning />;
}With reportAll: true, as in the strict preset, a use that is not obviously
wrong is reported too, until it has a comment that explains it:
function Clock({ now }) {
return (
<span suppressHydrationWarning>
{now.toLocaleTimeString("en-US", { timeZone: "UTC" })}
</span>
);
}Correct
function Clock({ now }) {
return (
<div>
<span suppressHydrationWarning>
{now.toLocaleTimeString("en-US", { timeZone: "UTC" })}
</span>
</div>
);
}
function Title() {
return <h1>Dashboard</h1>;
}
export function RootLayout({ children }) {
return (
<html lang="en" suppressHydrationWarning>
<body>{children}</body>
</html>
);
}With reportAll: true, a use with an eslint-disable comment that gives the
reason:
function Clock({ now }) {
return (
<div>
{/* eslint-disable-next-line hydration-proof/audit-suppress-hydration-warning -- a live clock; the server time is replaced after hydration */}
<span suppressHydrationWarning>
{now.toLocaleTimeString("en-US", { timeZone: "UTC" })}
</span>
</div>
);
}Options
| Option | Type | Default | Description |
|---|---|---|---|
| allowOn | string[] | ['html', 'body']: theme and extension scripts change their attributes before React hydrates | Elements where any use is accepted. |
| reportAll | boolean | false | Report every other use too, so each one must be justified in a disable comment. |
{
rules: {
'hydration-proof/audit-suppress-hydration-warning': ['error', { allowOn: ['html', 'body', 'ThemeProvider'], reportAll: false }],
},
}allowOn(string array, default['html', 'body']): element or component names where any use is accepted. Set it to[]to check<html>and<body>as well.reportAll(boolean, defaultfalse): also report uses that are not obviously wrong. Thestrictpreset turns this on.
Messages
What ESLint prints for this rule, word for word:
suppressHydrationWarningon<<tag>>only covers its own attributes and text, not the elements inside it: a mismatch in a child is still an error. Put it on the element whose content differs.suppressHydrationWarningon<<tag>>has nothing to suppress: its attributes and text are static. Remove it so that real mismatches added later are not hidden.suppressHydrationWarningon<<tag>>does nothing unless the component passes it to an HTML element. Put it on the element that renders the differing content, or make sure<tag>forwards it.suppressHydrationWarninghides hydration mismatches on<<tag>>. Render the same value on the server and in the browser instead, or explain why it is needed in an eslint-disable comment.- Remove suppressHydrationWarning.
When not to use it
When a design system passes suppressHydrationWarning through many wrapper
components on purpose: add those components to allowOn instead of turning
the rule off.
Related
no-date-in-renderandno-timezone-without-explicit-timezone: fixing the cause is usually better than suppressing it.- Intentional differences (suppressHydrationWarning),
as
hydration-proof testreports them - Theme hydration mismatches, the case
<html>is allowed for - Extra attributes from the server,
what browser extensions cause on
<html>and<body>