fix: React 19 clusterer infinite loop (#19) + SSR document crash#22
Open
w3di wants to merge 1 commit into
Open
fix: React 19 clusterer infinite loop (#19) + SSR document crash#22w3di wants to merge 1 commit into
w3di wants to merge 1 commit into
Conversation
5e6fc91 to
c83589b
Compare
… crash - YMapCustomClusterer: stop forwarding `ref` to the reactified clusterer. React 19 re-invokes callback refs null->value on every render, and reactify composes the forwarded ref into an unstable callback ref, so the clusterer re-binds each render and loops with 'Maximum update depth exceeded'. The root fix belongs in reactify (CDN); not forwarding the ref is the only lever at the package level. Fixes fede4ka1245#19. - EventBus: create the underlying EventTarget lazily so the constructor does not touch `document` at import time. Fixes SSR 'document is not defined'.
c83589b to
848fda5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two issues when using the package with React 19.
1. Infinite re-render loop in
YMapCustomClusterer(fixes #19, related to #15)Rendering
<YMapCustomClusterer>under React 19 throwsMaximum update depth exceededand the page hangs.Root cause: React 19 changed callback-ref semantics — refs are re-invoked
null -> valueon every render (not only mount/unmount).YMapCustomClustererforwardsrefto the reactifiedYMapClusterer, so under React 19 the reactified clusterer re-binds on every render and loops through its internalsetState(onRender).Confirmed by several users in #19 on React 19.2.0.
2.
document is not definedduring SSREventBuscallsdocument.appendChild(...)in its constructor, and a module-levelmapEventBusis created at import time. On the server (e.g. Next.js prerender)documentdoes not exist, so importing the package throws.Fix
YMapCustomClusterer: forwardrefonly on React <= 18 (parseInt(React.version, 10) < 19). On React 18 the imperative clusterer handle keeps working exactly as before; on React 19 the ref is skipped to avoid the infinite loop. This keeps backward compatibility and only changes behaviour where it currently crashes.EventBus: create the underlyingEventTargetlazily via a getter, so the constructor no longer touchesdocumentat import time.Source-only changes;
npm run build(vite build && tsc) passes.Note
On React 19 the
ref(imperativeYMapClustererhandle) is not exposed, since forwarding it is exactly what triggers the loop. If you prefer a different approach for exposing the handle on React 19, happy to adjust.