-
Notifications
You must be signed in to change notification settings - Fork 65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Breaking change with latest React experimental builds #260
Comments
Thank you so much for this report @gurkerl83! We'll look into it, and if you have any suggestions for implementing a fix we will happily accept PRs 🙏 |
I did some digging into the recent changes in React and may have been able to identify the problem. The initial report from above describes an error thrown when server-side generated components no longer match those on the client-side. This change of application behavior was introduced in the following commit. In the same commit, further changes are made, with at least the following leading to another problem (assuming error throwing is disabled).
Local tests show that the condition statement "if/else" block is wrong; the delete operation must always be executed. // *1 The delete operation needs to be called anyway; otherwise, DOM and React get out of sync, meaning phantom DOM entries (duplicated DOM Elements) get generated when re-rendering occurs. Those elements do not have a corresponding react component in the dev tools. // *2 Throwing errors have to be optional, not mandatory, options to think about
I will open a related issue in the React project and leave a link to it. Thx! |
Thank you @gurkerl83 for the digging 🙏 |
is there any update on this, or anything I could help with? I am facing the same issue after an update to React 18 (I am using NextJs) |
Hi, unfortunately I have sad news, the final version of React 18 no longer supports the approach used in Fresnel (prepare multiple variants of a component on the server, send both to the client and select the respective variant on the client). In React, this very selection performed at the client is called DOM patching. In my opinion, the way this so-called DOM patching is now implemented in React has flaws; actual errors are thrown across the library. I've looked at the source code of the affected places and everything I know about throwing and catching errors unfortunately doesn't apply here. Imagine if there were multiple, say 10 component pairs; it seems that error handling is repeatedly delegated to the root node of the application. Attempts to catch the errors locally in suspense boundaries have also failed. On the Fresnel project page it should be pointed out that the library is currently not compatible with React 18. One of the core contributors has given a hint how the approach used by Fresnel could be implemented after all see here. facebook/react#23381 (comment) Maybe Fresnel can be adjusted to this, although I don't understand that exactly.
|
Will update the README with a note next week after I get back from OOO, thanks again for the research 👍 |
First attempts to solve the problem draw a smile on my face. I follow the second option suggested by Dan.
Necessary steps
Where the adjustments are necessary?
In fact, only the component selected at the client gerate fires; this seems great so far. I test this both with the variants supported by Fresnel
The error messages are gone, but other aspects need to be considered to see if this can really be the solution concept. I'll keep you updated.... Thx! |
Awesome @gurkerl83! Thank you for digging into this 🙏 |
This comment was marked as outdated.
This comment was marked as outdated.
Any update on this? :( |
Unfortunately not :( |
Unfortunately things are very busy over here ATM. Will happily review/accept PRs for this approach, and we can discuss more over there 👍 |
Any updates on this? Or an alternative, that is not pure css? 🙏 |
Hopefully, the following is not another false positive; it seems two things have to happen to resolve the compatibility issue. A: A minor modification in fresnels sources The affected component is ResponsiveProvider in the file DynamicResponsive.
B: A Different approach to how the Media component gets consumed in the userland is necessary B.1: Add the following Suspender component
B.2: Use the Suspender component within Suspense as follows here for a mobile drawer
B.3: Use the Suspender component within Suspense as follows here for a desktop drawer
B.4: Use the components in Media using the render props variant
I can provide a merge request in the coming days. A question remains. Should the Suspense boundary, including the Suspender component, be integrated into a library or live in the userland? |
That's a great question. Would you mind elaborating a bit on what the And in your example If I'm understanding correctly: <Suspense fallback={foo}>
<Media><SomeComponentThatSuspends /></Bar>
</Suspense> The upper suspense boundary would never fire and be unexpectedly claimed by the buried suspense boundary in |
@damassi React 18 does not remove unmatched elements when server and client components differ during the first hydration attempt anymore. This was the default behavior before React 18; unfortunately, they are more strict now. The general idea is to suspend the component that does not match the current breakpoint condition before the initial hydration attempt gets executed; the Suspender component does that. The example provided is for the render props variant fresnel supports. I have not looked at the component variant yet, but I guess the Suspense / Suspender combo needs to be integrated directly into fresnel. One important thing is that only the component fire's lifecycles meet the current breakpoint condition.
It does not; see the respective desktop and mobile drawer components.
I guess you are right. When a component can be suspense, the components need an explicit suspense boundary. On the other hand, an outer suspense boundary renders first. If the component does not match the current breakpoint, the suspender blocks the inner component from rendering. To get the correct behaviour including fallbacks, docs need to describe those situations carefully. I tried a lot of things involving suspense boundaries every time. I´m pretty convinced there is no other way around it. Thx! |
Thanks for the overview @gurkerl83 👍 A couple things:
With these two things, the best I can suggest here is that we fork Fresnel to implement your solution, and that we return to this once I get back. Once we're ready to do a proper integration we can merge the fork back into main. Again, really appreciate all of your investigation here 🙏 |
Hi there, i've recently used the latest next.js which uses react v18. would love to contribute on this |
hey guys any updates? would greatly appreciate any help as I too am impacted by this issue |
@damassi or someone have a some news about this problem? |
No news unfortunately. Will gratefully accept PRs to fix the problem! |
Have figured it out, I will share something next week! |
Amazing 🙏 |
I post the required strategy first. The solution is all about suspense, in combination with a few instruments to suspend unmatched components in the proper order. Please read the comments made in the components carefully and provide feedback. The components I describe here is based on a custom implementation without using fresnel. I wanted to ensure that fresnel avoids any magic. Fresnel's implementation detail is confusing, especially when stacking several stacked providers. I made changes to fresnel locally to reflect those changes; the props are slightly different. All hydration errors are gone! Although all components get pre-rendered on the server, only the relevant component, which matches the current breakpoint, gets mounted on the client, exactly what we wanted. Some prove this is working; look at the deployed version of our web page, with responsive drawers, titles, and table of contents in place. Look at the console, and you should not see any error. https://millipede-docs-git-refactor-sitemap-gurkerl83.vercel.app/de/docs/perspective/strategy You can also verify that the suspense boundaries un- and re-suspend on resize in the components tab of react dev tools. The node names are a bit cryptic because it is an optimised, almost production version. SuspenseWrapper
Suspender
suspense - not related to reacts suspense component
To establish the context, here is the provider and how it is consumed. Media hook - the utilisation of useTransition is essential, the result includes isPending, which is served through context to the relevant suspense wrappers
MediaProvider
Consumer
Note: Thx! |
I still have hydration errors if i remove disableDynamicMediaQueries @ react 18.2.0, next 13.4.13 within app folder, fresnel 6.2.0 |
Ah, we're not using the new |
no we are not yet using the new app folder or the layouts functionality therein |
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 removed |
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. |
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. |
Yeah, the one thing i noticed that was different between our apps and the example with the use of |
Does this mean that so long as you are still using |
@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. |
I will hopefully have some time this week to try this out and sure, will report back. Thanks. |
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! |
Unfortunately I also still see the hydration errors after updating react to v18.2.0 😞 |
Just put up a PR that I hope resolves this issue! Check it out: #341 |
🚀 Issue was released in |
🚀 Issue was released in |
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:
and report back? |
cc @Geoff-Ford, @boylec, @alyustik |
checked on both pages and app routers - works like charm <3 |
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 👍 |
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. |
@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. |
@pawanrana1992 - if there's an issue with Next 14, please file a new issue and be detailed in what problem you're facing 🙏 |
@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. |
I can share my boilerplate, maybe it will help you (no ts and no tailwind there unfortunately): https://github.com/alyustik/next_boilerplate/ |
Thats a good point about setting up an app-directory example. I can do that 👍 (but likely won't be today) |
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
facebook/react@848e802
Recent commits made towards their new hydration approach
https://github.com/facebook/react/commits/51c8411d9dab33290b794fe716b9514e7db1fb68/packages/react-reconciler/src/ReactFiberWorkLoop.new.js
Thx!
The text was updated successfully, but these errors were encountered: