mg901/styled-breakpoints

useBreakpoint issues with SSR (eg Next.js)

Closed this issue ยท 7 comments

I came across a bug in my project yesterday and I think have now traced it to styled-breakpoints.

I've made a minimal reproduction which you can find at https://github.com/tremby/next-mq-bug

The main branch has the broken case, which is also deployed at http://next-mq-bug-1.surge.sh/

In this reproduction, I initialize a variable mobile, then in a try/catch block I run the useBreakpoint hook. I have to run it in a try/catch because window does not exist during server-side rendering, and it's impossible to know how wide the user's browser window is. Without the try/catch block, an error would be thrown here: https://github.com/mg901/styled-breakpoints/blob/master/react-styled/index.js#L9

Whichever version of the display initialized mobile to the value matching the width of the viewport at load time, displays correctly. The other version displays incorrectly. The wrong styled-components classes have been added to the wrong elements. On resizing so that the media query flips, the version which displayed correctly still displays correctly. The version which started out wrong is still wrong.

Here are some screenshots.


After hitting refresh at a narrow width:

Screen Shot 2020-12-04 at 20 16 15


Without refresh, after then resizing to be wider:

Screen Shot 2020-12-04 at 20 16 25


After hitting refresh at that wider width:

Screen Shot 2020-12-04 at 20 16 29


And then after resizing to be narrower again without hitting refresh:

Screen Shot 2020-12-04 at 20 16 36


I then made my own implementation of useBreakpoint (albeit limited to a hard-coded media query) and I do not get the same bug. In my version I don't actually need the try/catch block either, since everything which tries to use window happens in useEffect, and effects don't run at SSR time. That version is on my "without-styled-breakpoints" branch, and is deployed here: http://next-mq-bug-2.surge.sh/

If you are open to a rewrite of your useBreakpoint function I could give it a shot. Or do you think the bug is actually elsewhere, like in styled-components or in Next.js?

Incidentally, why does the current implementation put a resize handler on window? This seems wasteful. If it's meant as a fallback for when matchMedia isn't supported, it might not be worth having; https://caniuse.com/matchmedia says globally matchMedia has 99.02% support, and for cases where it really matters the developer could add a polyfill.

...this implementation isn't even using the change event of the media query. I'm rewriting it; will open a PR once it's working.

Done; please see the linked pull request.

๐ŸŽ‰ This issue has been resolved in version 9.0.6 ๐ŸŽ‰

The release is available on:

Your semantic-release bot ๐Ÿ“ฆ๐Ÿš€

Hi, I've encountered a weird bug when deploying next js app to vercel.

Everything is okay when open the deployed version on macOS / andoroid browser such as chrome/ safari/ firefox,
but when I tried to open it on iOS /iPhone browser such as chrome / safari, encountered error.

Tried remove useBreakpoint, and everything okay again.

I suggest you open a new issue with more detail. The issue I described, and which this ticket is about, has been resolved.

mg901 commented

@fatehwaharp, good time. Did you manage to solve your problem? If not, why didn't you open an issue? What error were you getting?