Since upgrading to React 16 I get this error message:
warning.js:33 Warning: Expected server HTML to contain a matching <div> in <body>.
What is generally causing this error message and how can it be fixed?
Since upgrading to React 16 I get this error message:
warning.js:33 Warning: Expected server HTML to contain a matching <div> in <body>.
What is generally causing this error message and how can it be fixed?
If you use ReactDOM.hydrate
to start web application, you will see this warning.
If your application does not use server-side rendering (ssr
), please use ReactDOM.render
to start.
suppressHydrationWarning={true}
prop can also be used on the rendered element. However, as documentation points, this prop must be used scarcely. The better solution is using hydrate()
or render()
appropriately: reactjs.org/docs/react-dom.html#hydrate –
Gloam If your HTML code is like
<table>
<tr>
you can get this error.
To get around it, use the <tbody> tag like
<table>
<tbody>
<tr>
Don't forget to close the tag(s)!
<div>
inside the parent <ul>
. Fixed it by changing the <div>
to <li>
. –
Forenoon If you use ReactDOM.hydrate
to start web application, you will see this warning.
If your application does not use server-side rendering (ssr
), please use ReactDOM.render
to start.
suppressHydrationWarning={true}
prop can also be used on the rendered element. However, as documentation points, this prop must be used scarcely. The better solution is using hydrate()
or render()
appropriately: reactjs.org/docs/react-dom.html#hydrate –
Gloam If you're using Server Side Rendering like NextJS, delete recent code and compare if you've tried to access a variable directly inside of Component scope where DOM is not guaranteed yet. For me, it was:
import { i18n } from 'i18n'
export default function SomeComponent() {
const initLanguage = i18n.language <---- causing error
return ...
}
If you need to access such properties, access it within useEffect
, so as to make sure that document
is already established by then. It is kinda equivalent to componentDidMount()
:
import { i18n } from 'i18n'
import { useEffect, useState } from 'react'
export default function SomeComponent() {
const [initlanguage, setInitLanguage] = useState('en')
useEffect(() => setInitLanguage(i18n.language), [])
return ...
}
This seems to be because of Browsersync inserting a script tag in the body on client side that does not exist on server side. Thus React fails to attach to the server render.
I got this using material UI by trying to do const searchParams = new URLSearchParams(process.browser ? window.location.search : '')
at the top of the react component in my NextJS app with material-ui SnackBar, I was able to remove the error by putting this in a useEffect
hook.
Entire component for reference:
export default function SnackBarMessage() {
const [requestLogin, setRequestLogin] = useState(false)
const handleClose = (event, reason) => {
if (reason === 'clickaway') {
return
}
setRequestLogin(false)
}
useEffect(() => {
// had to move into a useEffect hook
const searchParams = new URLSearchParams(process.browser ? window.location.search : '')
const hasRequestLogin = Boolean(searchParams.get('requestLogin'))
if (hasRequestLogin) {
setRequestLogin(true)
}
}, [])
return (
<>
{requestLogin && (
<Snackbar open={requestLogin} autoHideDuration={6000} onClose={handleClose}>
<Alert onClose={handleClose} severity='error' style={{ fontSize: '18px' }} elevation={6}>
Please Log Back In
</Alert>
</Snackbar>
)}
</>
)
}
In my case I got an error when upgrading to Next.js 13, specifically when using Drawer
from @mui/material
. It seems switching to server side components is not easy.
return (
<Drawer
anchor="left"
onClose={onClose}
open={open}
PaperProps={{
sx: {
backgroundColor: 'neutral.900',
color: '#FFFFFF',
width: 280
}
}}
sx={{zIndex: (theme) => theme.zIndex.appBar + 100}}
// 'persistent' or 'permanent' throws error
variant="temporary"
>
{content}
</Drawer>
);
If using Remix SSR hydration and you see an error like:
Warning: Expected server HTML to contain a matching <head> in <html>
there is a known issue where browser plugins can cause this issue (you can verify it's plugins by trying to load the page in Incognito mode).
See this Github issue: https://github.com/remix-run/indie-stack/issues/184
Apparently you can disable this warning/error by adding suppressHydrationWarning={true}
to your <html>
tag but this didn't work for me
This is also described in Remix's Gotchas: https://remix.run/docs/en/1.14.3/pages/gotchas#md-browser-extensions-injecting-code
This has been a frustrating and known issue for a long time and I have no idea why the Remix team has still not fixed this :(
In my case it was because of using PersistGate
and react-loadable
.
if you using this libraries, you could use preloadAll instead of preloadReady
In my case i installed REACTFUL and it do a render so different by default install:
src/renderers/dom.js
ReactDOM.hydrate(
<App initialData={window.__R_DATA.initialData} />,
document.getElementById('root'),
);
src/renderers/server.js
const initialData = {
appName: 'Reactful',
};
return Promise.resolve({
initialData,
initialMarkup: ReactDOMServer.renderToString(
<App initialData={initialData} />,
),
pageData,
});
care with initialData!
i fix it changed dom.js like it, attention to initialData is important:
const renderMethod = module.hot ? ReactDOM.render : ReactDOM.hydrate;
const initialData = {
appName: 'Reactful',
};
renderMethod(
<App initialData={initialData} />,
document.getElementById('root'),
);
The issue can be caused because the client and server mismatch during HMR updates
I resolved that way:
const renderMethod = !!module.hot ? ReactDOM.render : ReactDOM.hydrate
const renderMethod = !!module.hot ? ReactDOM.render : ReactDOM.hydrate
renderMethod(
<AppContainer>
<Comp />
</AppContainer>,
document.getElementById('root')
)
The solution: Use incognito
Apparently, my case is that the extensions I have caused this. So the way I solve it is just go to Incognito mode where most of my extensions are disabled there. Adding this answer because none seem to try to answer directly.
Looks like you're trying to access a prop in a dom before is ready. You can use a structure like this:
{(variable) && sameVariable}
I'm assuming you are using ssr. The warning is about attempting to render before there is a window object. You need to hydrate.
ReactDOM.hydrate(<App />, document.getElementById("home"))
What I don't understand, is that the App component is being served static by express. Why is it trying to render before it is served? Bring on the comments.
© 2022 - 2024 — McMap. All rights reserved.
NextJS
) just deleting the build output directory.next
and restarting the dev server made the problem disappear. – Immeasurable