# audit-suppress-hydration-warning

> A suppressHydrationWarning ESLint rule: it reports the attribute where it does nothing or hides more than intended, and in strict mode every use.

Source: https://hydration.jscrate.dev/docs/rules/audit-suppress-hydration-warning
Last updated: 2026-09-18

`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 |
| 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`,
  `ref` and 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` (the `strict` preset), **every other use**
  (`audit`), so each suppression needs an `eslint-disable` comment 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](https://hydration.jscrate.dev/docs/eslint#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:

```jsx
<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](https://hydration.jscrate.dev/docs/issues/hp6001) to [HP6003](https://hydration.jscrate.dev/docs/issues/hp6003)),
so you can check what each one suppresses.
[When suppressHydrationWarning is safe](https://hydration.jscrate.dev/docs/guides/suppresshydrationwarning)
covers the cases where the attribute is the right tool.

## Incorrect

```jsx
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:

```jsx options='{"reportAll":true}'
function Clock({ now }) {
  return (
    <span suppressHydrationWarning>
      {now.toLocaleTimeString("en-US", { timeZone: "UTC" })}
    </span>
  );
}
```

## Correct

```jsx
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:

```jsx options='{"reportAll":true}'
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. |

```js title="eslint.config.mjs"
{
  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, default `false`): also report uses that are not
  obviously wrong. The `strict` preset turns this on.

## Messages

What ESLint prints for this rule, word for word:

- `suppressHydrationWarning` on `<<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.
- `suppressHydrationWarning` on `<<tag>>` has nothing to suppress: its attributes and text are static. Remove it so that real mismatches added later are not hidden.
- `suppressHydrationWarning` on `<<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.
- `suppressHydrationWarning` hides 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-render`](https://hydration.jscrate.dev/docs/rules/no-date-in-render) and
  [`no-timezone-without-explicit-timezone`](https://hydration.jscrate.dev/docs/rules/no-timezone-without-explicit-timezone):
  fixing the cause is usually better than suppressing it.
- [Intentional differences (suppressHydrationWarning)](https://hydration.jscrate.dev/docs/causes/suppressed),
  as `hydration-proof test` reports them
- [Theme hydration mismatches](https://hydration.jscrate.dev/docs/causes/theme), the case `<html>` is
  allowed for
- [Extra attributes from the server](https://hydration.jscrate.dev/docs/errors/extra-attributes-from-the-server),
  what browser extensions cause on `<html>` and `<body>`
