artsy / fresnel

An SSR compatible approach to CSS media query based responsive layouts for React.
https://artsy.github.io/blog/2019/05/24/server-rendering-responsively
Other
1.26k stars 65 forks source link

Breaking change with latest React experimental builds #260

Closed gurkerl83 closed 1 year ago

gurkerl83 commented 2 years ago

Hi, I have used this library for a while now, also adopting React 18 using their experimental builds. The latest refactorings in Reacts hydration handling approach (including throwing errors when the content of a component does not match anymore) indicates a breaking change towards fresnels idea of sending variants of an element (desktop/mobile) prepared by a server back to the client.

Testing the latest experimental versions of React, I have identified the last version where fresnel is still compatible; a newer nightly version from the next day up to the latest experimental version from today is incompatible with fresnel.

Latest compatible version: 18.0.0-rc.0-next-fa816be7f-20220128 First incompatible version: 18.0.0-rc.0-next-3a4462129-20220201 Most recent incompatible version: 18.0.0-rc.0-next-79ed5e18f-20220217

Looking at the source code and commit messages where this shift all started seems they throw an error when a mismatch occurs. It seems they are not just warning the user anymore but engaging in resolving. This results in a client-side render, and all server-side output is lost.

Communication with the React team is essential to keep fresnels approach working with the upcoming React version. It is still an excellent strategy to prepare multiple versions of a component at the server-side and decide on the client which one to pick.

See the commit message for the new approach React follows https://github.com/facebook/react/commit/848e802d203e531daf2b9b0edb281a1eb6c5415d

Recent commits made towards their new hydration approach https://github.com/facebook/react/commits/51c8411d9dab33290b794fe716b9514e7db1fb68/packages/react-reconciler/src/ReactFiberWorkLoop.new.js

Thx!

JPaulDev commented 2 years ago

How is anyone using SSG/SSR with react getting it to work if not for the way fresnel does it? anything other than their(artsy / fresnel) way results in flickers of animations / components being added and removed etc no matter what you do.

Are many people just not using next SSR/SSG yet? I just discovered fresnel recently. Obviously we can dynamically render anything with next dynamic but that doesn't seem to be a very good solution to me.

Sure this can be done with pure css (along with extra markup), I assume that is what people do? fresnel just provided a clean way to do it all.

damassi commented 2 years ago

@JPaulDev - FWIW, our primary way of handing responsive SSR style stuff is via our component library Palette, which is built on top of styled-system. It uses the notion of responsive props: https://palette.artsy.net/guides/responsive/, which is by far the nicest / most lightweight way we've encountered to do this kind of thing. I would highly recommend looking into styled-system! It's like tailwind (functional CSS), but you don't have to mess with classNames and strings and extra tooling, and the responsive props idea is brilliant.

That said, there are situations where we need a full, different layout, and that's where Fresnel comes in. But those situations are rare, and in general we prefer the below notation where possible:

const App = () => {
  return (
    <>
      <MobileLayout display={["block", "none"]} />
      <DesktopLayout display={["none", "block"]} />
   </>
  )
}

Of course, there's still the issue with unnecessarily firing effects within invisible components, but generally speaking we don't have layouts that are that different from our desktop, or can't be stacked vertically, so that's not much of a concern for us.

We've written all about our approach here: https://artsy.github.io/blog/2019/05/24/server-rendering-responsively/

(As a heads up, we're getting closer to React 18 for Artsy.net, and when we start the upgrade process we're going to be giving this Fresnel suspense issue another look.)

JPaulDev commented 2 years ago

Thanks damassi that's actually a really useful article. Hope you guys manage some way to get fresnel working again, and hopefully react themselves eventually release responsive components like dan was talking about.

kaguya3222 commented 1 year ago

@damassi Sorry for the direct ping, but is there any update? Does this library have support for React 18 ?

omattman commented 1 year ago

Any updates on this?

damassi commented 1 year ago

Hi all! No updates yet, but one somewhat good piece of news here is that the latest version of Next.js will hide hydration errors in the bottom left bubble, and production builds don't emit it. So technically speaking, the dev/user experience is no longer totally broken for next users. For react users not using Next, will still have to wait unfortunately; we haven't had the resources to prioritize the React 18 update but will happily accept contributions from users who might want to take a stab at the approach outlined above. It is close.

boylec commented 1 year ago

Update: After some further testing we noticed some issues with Next, specifically the error

This Suspense boundary received an update before it finished hydrating

I'm not sure why this was not appearing during testing of #290, but out of caution we backed out of the suspense integration, deprecated v5, published a v6 (πŸ˜“) and are officially suggesting that folks use the approach as outlined in the README:

Due to React 18 more strictly handling server-side rendering rehydration full SSR support is incompatable with any version greater than 17. See #260 to track our progress in fixing this issue, and Dan Abromov's facebook/react#23381 (comment).

In the meantime -- for users of server-side rendering features -- you can disable DOM cleaning optimizations by setting disableDynamicMediaQueries on the context like so and things should work:

<MediaContextProvider disableDynamicMediaQueries>
  <Media at='xs'>
    <MobileApp />
  </Media>
  <Media greaterThan='xs'>
    <DesktopApp />
  </Media>
<MediaContextProvider>

Note that this will fire all effects within sub components for each breakpoint on re-hydration. For some users this could be an issue; for many others, no problem at all.

Many apologies for any confusion this may have caused. We should have tested this more thoroughly on our end before publishing a major version update.

For what its worth, the implementation inspired by @gurkerl83 (v5.0.2) seems to be working great for us at the moment:

next v13.3 react v18.2 fresnel v5.0.2

We have not observed any of these errors - we're not using the MUI library.

damassi commented 1 year ago

That is great to hear @boylec πŸ‘ I'll need to do some more confirmation over here before I update the readme to encourage.

boylec commented 1 year ago

That is great to hear @boylec πŸ‘ I'll need to do some more confirmation over here before I update the readme to encourage.

Funny: As soon as I said that I started seeing the issue and I am unable to discern what the cause is.

boylec commented 1 year ago

For whatever its worth:

I'm not sure what changed - I suspect it is on the Next.JS side - but we are using fresnel with no issues now with Next.js version 13.4.7 and React version 18.2.0. We are not doing anything special, just using the package the way we were when we were on Next 12.x and React 17.x.

We've been using it in production for months now with no errors/issues being reported in dev or production builds.

I'd be curious if anyone else could confirm whether or not they are able to use this package as well with the latest Next.JS/React.

damassi commented 1 year ago

YUP! No issues over here, and we're now using it in two separate next apps. Thank the lord, lol. Going to close this and update the README with a note about Next. Been meaning to for a bit πŸ‘

damassi commented 1 year ago

Updated here: https://github.com/artsy/fresnel/pull/328

EDIT: Based on the below, tried to upgrade the next app in our examples and no go. So reverted this PR for the time being. I wish i had more answers at this time.

alyustik commented 1 year ago

I still have hydration errors if i remove disableDynamicMediaQueries @ react 18.2.0, next 13.4.13 within app folder, fresnel 6.2.0

damassi commented 1 year ago

Ah, we're not using the new app folder over here due to unfortunate publicRuntimeConfig depreciations and docker. @boylec - are you using layouts?

boylec commented 1 year ago

Ah, we're not using the new app folder over here due to unfortunate publicRuntimeConfig depreciations and docker. @boylec - are you using layouts?

no we are not yet using the new app folder or the layouts functionality therein

alyustik commented 1 year ago

I've tried to roll back my project to pages directory and still no luck. Then I have cloned this example https://github.com/artsy/fresnel/tree/main/examples/nextjs, have removeddisableDynamicMediaQueries and updated next version to 13.4.7 and i still have hydration errors

damassi commented 1 year ago

Ugh, never ending. I just tried this in the example app, and yup, upgrading everything, and still seeing the hydration error. No clue. Our two fairly vanilla next apps work great, with no issues at all and we're using this feature all over.

As usual, swamped at work but will try to find a moment to look more into this. Going to revert the other PR in the meantime.

boylec commented 1 year ago

I too was able to reproduce using the example.

We use Media components quite robustly as well across our entire app - which is not a simple app - with no hydration issues.

Not sure what the difference is between the example app and my own app sorry for the false hopes folks.

damassi commented 1 year ago

Yeah, the one thing i noticed that was different between our apps and the example with the use of _app. I even tried adding that here, but no go.

Geoff-Ford commented 1 year ago

Does this mean that so long as you are still using pages, we can use latest React and Next without issue? I have no intention of switching to app as site is predominantly SSG.

damassi commented 1 year ago

@Geoff-Ford - We have a few examples of this working, as if there was never a problem at all. Artsy has a few next.js apps that have been spun up recently and we use fresnel with no problem. Boylec, too. Unfortunately, trying to update the example app and we still see the hydration error. So there's some mystery here. I would suggest trying it out on your end with latest next and react and react-dom and reporting back here.

Geoff-Ford commented 1 year ago

I will hopefully have some time this week to try this out and sure, will report back. Thanks.

gurkerl83 commented 1 year ago

In my view, the issue of hydration errors persists despite the advancements in React 18.2, as well as in Canary and Next.js 13. These updates haven't effectively addressed the problem. The root of the issue lies deep within React's architecture, and it appears to be an intentional design choice, leaving us with limited options for a fix. You may not be encountering hydration errors as frequently due to less stringent client fallback mechanisms, but the underlying issue remains unresolved. Thx!

Geoff-Ford commented 1 year ago

Unfortunately I also still see the hydration errors after updating react to v18.2.0 😞

mgreenw commented 1 year ago

Just put up a PR that I hope resolves this issue! Check it out: https://github.com/artsy/fresnel/pull/341

artsyit commented 1 year ago

:rocket: Issue was released in v7.0.0 :rocket:

artsyit commented 1 year ago

:rocket: Issue was released in v7.0.0 :rocket:

damassi commented 1 year ago

Pretty sure this has been definitely fixed in 7.1.3 (for Next.js users specifically, as tested in the examples folder). Can y'all run:

yarn install @artsy/fresnel@latest

and report back?

damassi commented 1 year ago

cc @Geoff-Ford, @boylec, @alyustik

alyustik commented 1 year ago

checked on both pages and app routers - works like charm <3

damassi commented 1 year ago

Well then: CASE CLOSED! 🍻 Thanks again to @mgreenw for his brilliantly simple solution to the problem.

Folks, keep an eye out as you use it and file any issues that might come up πŸ‘

Geoff-Ford commented 1 year ago

Happy days!!! Can confirm all good! Such a relief as this was always at the back of my mind every time I read about new react/nextjs features that I couldn't update to.

pawanrana1992 commented 1 year ago

checked on both pages and app routers - works like charm <3

@alyustik @Geoff-Ford thanks for resolutions, And I need a help to integrate this @artsy/fresnel library in nextjs@14, I don't found any example or configuration which can run the library smoothly in nexjs app directory. Could you pls help me get example configuration to configure the @artsy/fresnel inside nextjs@14 with tailwindcss if possible. I am stuck here and I need to move this any how, please help. thanks in advance.

damassi commented 1 year ago

@pawanrana1992 - if there's an issue with Next 14, please file a new issue and be detailed in what problem you're facing πŸ™

pawanrana1992 commented 1 year ago

@damassi sorry if miss guide you here, Actually I need setup/configuration inside app routing approach using nextjs@14. inside @artsy/fresnel I can only see pages routing example. Could you please help get the example project or doc to use @artsy/fresnel inside nextjs@14 or with app routing please.

alyustik commented 1 year ago

@alyustik @Geoff-Ford thanks for resolutions, And I need a help to integrate this @artsy/fresnel library in nextjs@14, I don't found any example or configuration which can run the library smoothly in nexjs app directory. Could you pls help me get example configuration to configure the @artsy/fresnel inside nextjs@14 with tailwindcss if possible. I am stuck here and I need to move this any how, please help. thanks in advance.

I can share my boilerplate, maybe it will help you (no ts and no tailwind there unfortunately): https://github.com/alyustik/next_boilerplate/

damassi commented 1 year ago

Thats a good point about setting up an app-directory example. I can do that πŸ‘ (but likely won't be today)