-
Notifications
You must be signed in to change notification settings - Fork 4
ECHOES-1266 Harden React 19 ref handling to prevent callback-ref update loops (useForwardedRef, compose-refs, radio-group attach refs) #658
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
Merged
david-cho-lerat-sonarsource
merged 1 commit into
main
from
david/fix-react-19-useforwardref
Mar 24, 2026
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
30 changes: 30 additions & 0 deletions
30
.yarn/patches/@radix-ui-react-compose-refs-npm-1.1.2-f0371f8267.patch
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| diff --git a/dist/index.js b/dist/index.js | ||
| index 5ba7a95bc7a29605f32aa010a14224ad87bf6589..699fc222db43d83ac2e3218c0aa5c9db46dc697d 100644 | ||
| --- a/dist/index.js | ||
| +++ b/dist/index.js | ||
| @@ -39,7 +39,9 @@ module.exports = __toCommonJS(index_exports); | ||
| var React = __toESM(require("react")); | ||
| function setRef(ref, value) { | ||
| if (typeof ref === "function") { | ||
| - return ref(value); | ||
| + if (value !== null) { | ||
| + return ref(value); | ||
| + } | ||
| } else if (ref !== null && ref !== void 0) { | ||
| ref.current = value; | ||
| } | ||
| diff --git a/dist/index.mjs b/dist/index.mjs | ||
| index 7dd9172a7228d70a25f708d0fd577cfc69ea15a8..d8a2f56ecb5951410e1a5748d9a8db56eb966351 100644 | ||
| --- a/dist/index.mjs | ||
| +++ b/dist/index.mjs | ||
| @@ -2,7 +2,9 @@ | ||
| import * as React from "react"; | ||
| function setRef(ref, value) { | ||
| if (typeof ref === "function") { | ||
| - return ref(value); | ||
| + if (value !== null) { | ||
| + return ref(value); | ||
| + } | ||
| } else if (ref !== null && ref !== void 0) { | ||
| ref.current = value; | ||
| } |
54 changes: 54 additions & 0 deletions
54
.yarn/patches/@radix-ui-react-radio-group-npm-1.3.8-6cdda6336a.patch
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| diff --git a/dist/index.js b/dist/index.js | ||
| index deae02992529c4daef1710bb7394a94edeea11f5..cb1ae63b7067854f3277ceb9a7cdb66735768e0e 100644 | ||
| --- a/dist/index.js | ||
| +++ b/dist/index.js | ||
| @@ -78,10 +78,10 @@ var Radio = React.forwardRef( | ||
| form, | ||
| ...radioProps | ||
| } = props; | ||
| - const [button, setButton] = React.useState(null); | ||
| - const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, (node) => setButton(node)); | ||
| + const button = React.useRef(null); | ||
| + const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, button); | ||
| const hasConsumerStoppedPropagationRef = React.useRef(false); | ||
| - const isFormControl = button ? form || !!button.closest("form") : true; | ||
| + const isFormControl = button.current ? form || !!button.current.closest("form") : true; | ||
| return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(RadioProvider, { scope: __scopeRadio, checked, disabled, children: [ | ||
| /* @__PURE__ */ (0, import_jsx_runtime.jsx)( | ||
| import_react_primitive.Primitive.button, | ||
| @@ -107,7 +107,7 @@ var Radio = React.forwardRef( | ||
| isFormControl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)( | ||
| RadioBubbleInput, | ||
| { | ||
| - control: button, | ||
| + control: button.current, | ||
| bubbles: !hasConsumerStoppedPropagationRef.current, | ||
| name, | ||
| value, | ||
| diff --git a/dist/index.mjs b/dist/index.mjs | ||
| index 46bb67f279d7e0a06cb177ad6a8b3de12745d4a5..808c57a8f43de24c89df3cfa3cf6b0f582ddf8e6 100644 | ||
| --- a/dist/index.mjs | ||
| +++ b/dist/index.mjs | ||
| @@ -37,10 +37,10 @@ var Radio = React.forwardRef( | ||
| form, | ||
| ...radioProps | ||
| } = props; | ||
| - const [button, setButton] = React.useState(null); | ||
| - const composedRefs = useComposedRefs(forwardedRef, (node) => setButton(node)); | ||
| + const button = React.useRef(null); | ||
| + const composedRefs = useComposedRefs(forwardedRef, button); | ||
| const hasConsumerStoppedPropagationRef = React.useRef(false); | ||
| - const isFormControl = button ? form || !!button.closest("form") : true; | ||
| + const isFormControl = button.current ? form || !!button.current.closest("form") : true; | ||
| return /* @__PURE__ */ jsxs(RadioProvider, { scope: __scopeRadio, checked, disabled, children: [ | ||
| /* @__PURE__ */ jsx( | ||
| Primitive.button, | ||
| @@ -66,7 +66,7 @@ var Radio = React.forwardRef( | ||
| isFormControl && /* @__PURE__ */ jsx( | ||
| RadioBubbleInput, | ||
| { | ||
| - control: button, | ||
| + control: button.current, | ||
| bubbles: !hasConsumerStoppedPropagationRef.current, | ||
| name, | ||
| value, |
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
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
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
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
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.