Next.js: SSR issue with dynamic responsive elements

Created on 22 Feb 2018  路  15Comments  路  Source: vercel/next.js


I'm using reactstrap (bootstrap) together with react-responsive for my site's responsive layout.
There is no problem when I'm using reactstrap alone.

However, when I mix react-responsive into the pages to show certain components only at certain screen breakpoints, I'm getting the following error in the browser console:

main.js:4530 Warning: Expected server HTML to contain a matching <div> in <div>.

  • [x] I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior



The error should not be showing up in the browser console.

Current Behavior



An error main.js:4530 Warning: Expected server HTML to contain a matching <div> in <div>. will appear in the console when ever a page is refreshed.

Steps to Reproduce (for bugs)


  1. Use react-responsive to render a component when a smaller screen size is matched.
  2. Refresh page
  3. Error should will show up in console.
  4. The page however appears to still work normally.

Context



I'm using reactstrap (bootstrap) together with react-responsive for my site's responsive layout.

There is no problem when I'm using reactstrap alone.

However, when I mix react-responsive into the pages to show certain components only at certain screen breakpoints, I'm getting the following error in the browser's console:

main.js:4530 Warning: Expected server HTML to contain a matching <div> in <div>.

Removing the responsive component will get rid of this error message too.

Although I'm not certainly sure what's the cause, I'm suspecting this has to do with the server side rendering. The mobile component was probably rendered dynamically on client but not on server side.

Is there anything I can do to fix this error? Any impact if the error is left unresolved?

Your Environment


| Tech | Version |
|---------|---------|
| next | 5.0.0 |
| node | 6.9.1 |
| OS | Win 10 |
| browser | Chrome |
| etc | |

Most helpful comment

Artsy has a good solution for responsive SSR rendering via @artsy/fresnel. Here's an example that works with Next, and a blog post.

All 15 comments

this is probably due to the responsive component rendering on the server side with a static width (you can't know the client viewport on the server ofcourse). The warning impacts the time before your app becomes interactive, since React has to repaint certain components. I hope that answers your question. Going to close this as it's unrelated to Next.

@timneutkens Just wondering, will this actually impact nextjs' server rendering in any ways if this error is left as it is (unfixed)?

It won't effect SSR, that's why it's a warning coming from React, but you lose a few benefits of SSR, mainly that when the content is hydrated by React it doesn't have to re-render.

You can run that component with NO SSR. Problem will be fixed!

I have this issue too, and it effects production build. I'm using react-responsive, and I decide which layout to use by detecting window width(specifically by react-responsive's MediaQuery). But when it's SSR, I won't get device width, so it's always one layout being shown. Strange thing here is React doesn't re-render, so I'm getting the wrong layout & styles.

anyway I can fix this issue? @timneutkens

I guess I can run certain component without SSR. How can I achieve this? @xmanzero

You could use next/dynamic with ssr: false

Strange thing here is React doesn't re-render, so I'm getting the wrong layout & styles.

That is an issue I am now dealing with after porting a large scale project from Electrode to NextJS. It used to rerender the layout on the client, but now the width stays wrong (react-responsive is not updating), and although render method is called on the client, the React JS output is not affected.
Not sure how to solve it.

You could use next/dynamic with ssr: false

@timneutkens this does not work

@superical did you solve this?

Artsy has a good solution for responsive SSR rendering via @artsy/fresnel. Here's an example that works with Next, and a blog post.

@damassi Have you worked with artsy solution? It almost feels like going full circle having to implement media-breakpoints again ...

Hi @FBosler - yup, I work there. Did you have any questions? Fresnel solves a very specific problem, and that is how does one handle SSR rendering with responsive layouts (although it also works very nicely with client-side only code). The API is declarative via react components, so there's nothing that one needs to implement in CSS, etc; not sure what you mean?

@damassi Ahhh nice, I actually came across the blog before asking the question. It's well written. My question was only around adoption and stability of the solution. I am always a bit hesitant when a library does not seem to be mainstream yet.

What I meant by full circle, but this could also be due to some misconception on my side, is that it seems like by implementing these media breakpoints I wouldn't really be able to use say bootstraps gridsystem, would I?

You certainly could -- it's just a matter of passing in the same set of breakpoints that bootstrap's grid uses, like so:

const { MediaContextProvider, Media } = createMedia({
  breakpoints: {
    sm: 0,
    md: 768,
    lg: 1024,
    xl: 1192,
  },
})

And then from there can mix and match as needed

const App = () => (
  <MediaContextProvider>
    <Media at="sm">
      <div className='col-12'>
        <MobileApp />
      </div>
    </Media>
    <Media at="md">
      <TabletApp />
    </Media>
    <Media greaterThanOrEqual="lg">
      <DesktopApp />
    </Media>
  </MediaContextProvider>
)

@damassi
I was doing POC with @artsy/fresnel, for this problem.
found you ship the whole page over the wire with all breakpoints, it's just not the HTML but javascript is also shipping.
this is the issue link - https://github.com/artsy/fresnel/issues/156

to detect device width on the server-side, I am using CloudFront header
https://aws.amazon.com/blogs/aws/enhanced-cloudfront-customization/

cloudfront-is-tablet-viewer
cloudfront-is-mobile-viewer

I think the best solution to this problem is while SSG process we can pass breakpoints to generate static pages for the required screen sizes and use the CloudFront header to detect and ship the correct screen size page

Was this page helpful?
0 / 5 - 0 ratings