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

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.


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

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


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