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

Reactjs

Reactjs Problem Overview


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?

Reactjs Solutions


Solution 1 - Reactjs

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.

Solution 2 - Reactjs

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

Solution 3 - Reactjs

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

Solution 4 - Reactjs

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.

Solution 5 - Reactjs

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

Solution 6 - Reactjs

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

Solution 7 - Reactjs

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

Solution 8 - Reactjs

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

Solution 9 - Reactjs

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

{(variable) && sameVariable}

Solution 10 - Reactjs

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAntonView Question on Stackoverflow
Solution 1 - ReactjsJay HuView Answer on Stackoverflow
Solution 2 - ReactjsLuciaView Answer on Stackoverflow
Solution 3 - ReactjscatomaticView Answer on Stackoverflow
Solution 4 - ReactjsAntonView Answer on Stackoverflow
Solution 5 - ReactjsKevin DanikowskiView Answer on Stackoverflow
Solution 6 - ReactjsSayJeyHiView Answer on Stackoverflow
Solution 7 - ReactjspikamorfoView Answer on Stackoverflow
Solution 8 - ReactjsCarolina GonzalezView Answer on Stackoverflow
Solution 9 - ReactjsDifatha T. KariukiView Answer on Stackoverflow
Solution 10 - ReactjsDevinView Answer on Stackoverflow