This warning occurs during React hydration when server-rendered HTML contains attributes that the client-side code doesn't expect. In older React versions (pre-16), data-reactroot and data-reactid were internal attributes used by React. Modern React has removed these attributes, but the warning can still appear due to browser extensions or version mismatches.
This warning appears when React's hydration process detects a mismatch between the server-rendered HTML and the client-side React tree. Specifically, the server-rendered markup contains HTML attributes that the client doesn't recognize or expect. In React versions before 16, React automatically added internal attributes like data-reactroot (to mark the root element) and data-reactid (to uniquely identify each component in the tree). These attributes helped React reconcile the DOM during hydration. However, React 16 removed data-reactid entirely, and modern versions no longer add data-reactroot in most cases. If you're seeing this warning in a modern React application, it typically means you're either using an outdated version of React, have a mismatch between your server and client React versions, or browser extensions are injecting unexpected attributes into your HTML. The warning won't break your application, but it indicates that React had to do extra work during hydration, which can impact performance.
Check that your server and client are using the same version of React. Open your package.json and confirm the versions:
{
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}Delete your node_modules and lock file, then reinstall:
rm -rf node_modules package-lock.json
npm installRebuild your application to ensure both server and client bundles use the same React version.
For React 16-17, ensure you're using ReactDOM.hydrate() instead of ReactDOM.render():
// React 16-17
import ReactDOM from 'react-dom';
import App from './App';
const rootElement = document.getElementById('root');
ReactDOM.hydrate(<App />, rootElement);For React 18+, use hydrateRoot():
// React 18+
import { hydrateRoot } from 'react-dom/client';
import App from './App';
const rootElement = document.getElementById('root');
hydrateRoot(rootElement, <App />);Using the wrong API can cause hydration warnings.
Browser extensions like Grammarly, LastPass, or React DevTools can inject attributes into your HTML. Test in an incognito/private window with extensions disabled:
Chrome/Edge: Ctrl+Shift+N (Windows) or Cmd+Shift+N (Mac)
Firefox: Ctrl+Shift+P (Windows) or Cmd+Shift+P (Mac)
If the warning disappears, a browser extension is the cause. You can suppress the warning for specific elements:
<html suppressHydrationWarning>
<body suppressHydrationWarning>
{children}
</body>
</html>Note: Only use suppressHydrationWarning on elements where you expect external modifications (like <html> or <body>).
If you're still on React 15, upgrade to a modern version. React 16 removed data-reactid entirely:
npm install react@latest react-dom@latestKey migration changes:
- Replace ReactDOM.render() with ReactDOM.hydrate() for SSR
- Remove any code that relies on data-reactid or data-reactroot
- Update server rendering to use renderToString() or renderToStaticMarkup()
After upgrading, clear your build cache:
rm -rf .next # Next.js
rm -rf build # Create React AppRebuild and test your application.
Verify your server-side rendering produces clean HTML without extra React attributes. For static pages or when you don't need hydration, use renderToStaticMarkup():
import { renderToStaticMarkup } from 'react-dom/server';
// This doesn't add any React attributes
const html = renderToStaticMarkup(<App />);For pages that need hydration, use renderToString():
import { renderToString } from 'react-dom/server';
// This adds minimal attributes needed for hydration
const html = renderToString(<App />);In Next.js, this is handled automatically, but ensure you're not manually adding data-reactroot or data-reactid attributes in custom Document or layout components.
Historical Context: React 15 and earlier used data-reactid extensively to track component positions in the virtual DOM tree. Each element received a unique ID like "0.0.1.2", forming a hierarchical path. React 16's fiber architecture eliminated the need for these attributes, resulting in cleaner HTML output and smaller payloads.
Version-Specific Behavior:
- React 15: Always adds data-reactroot and data-reactid to all elements
- React 16-17: No data-reactid, data-reactroot only on root with hydrate()
- React 18+: Uses hydrateRoot(), minimal extra attributes
Next.js Considerations: Next.js handles hydration automatically. If you see this warning in Next.js, check for:
- Custom _document.tsx or _app.tsx modifications
- Third-party libraries rendering with old React versions
- Browser extensions (most common cause)
Production Impact: While the warning is cosmetic, hydration mismatches can cause React to discard server-rendered HTML and re-render from scratch, negating SSR performance benefits. In production builds, React may log fewer warnings, but the performance cost remains.
Debugging Technique: Use React DevTools Profiler to measure hydration time. If it's significantly slower than expected, you likely have attribute mismatches forcing React to rebuild the tree.
React.FC expects children prop to be defined
React.FC no longer includes implicit children prop
Warning: You provided a `selected` prop to a form field without an `onChange` handler
You provided a 'selected' prop without an onChange handler
Failed to load source map from suspense chunk
How to fix "Failed to load source map from suspense chunk" in React
Prop spreading could cause security issues
Prop spreading could cause security issues
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency