Anton
Anton

Reputation: 6033

React 16: Warning: Expected server HTML to contain a matching <div> in <body>

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?

Upvotes: 78

Views: 159198

Answers (14)

Vasilis Plavos
Vasilis Plavos

Reputation: 583

Check the source code of your app.

If the source code has 2 </body then you added body element twice by mistake.

Find it in your code and replace the inner body element to div element.

Upvotes: 0

Irfandy J.
Irfandy J.

Reputation: 1464

tldr;

The solution: Use incognito

For me

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.

Upvotes: 1

Markoorn
Markoorn

Reputation: 2565

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 :(

Upvotes: 1

Adilet Soronov
Adilet Soronov

Reputation: 139

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>
);

Upvotes: 1

Carolina Gonzalez
Carolina Gonzalez

Reputation: 1

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')
)

Upvotes: 0

Difatha T. Kariuki
Difatha T. Kariuki

Reputation: 51

Looks like you're trying to access a prop in a dom before is ready. You can use a structure like this:

{(variable) && sameVariable}

Upvotes: -1

Kevin Danikowski
Kevin Danikowski

Reputation: 5196

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>
      )}
    </>
  )
}

Upvotes: 2

pikamorfo
pikamorfo

Reputation: 31

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'),
);

Upvotes: 0

SayJeyHi
SayJeyHi

Reputation: 1841

In my case it was because of using PersistGate and react-loadable. if you using this libraries, you could use preloadAll instead of preloadReady

Upvotes: 0

Lucia
Lucia

Reputation: 13587

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 ...
}

Upvotes: 35

Devin
Devin

Reputation: 134

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.

Upvotes: -2

catomatic
catomatic

Reputation: 891

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)!

Upvotes: 46

Jay Hu
Jay Hu

Reputation: 428

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.

Upvotes: 38

Anton
Anton

Reputation: 6033

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.

Upvotes: 3

Related Questions