From 6cb4bc2947e0c164274ef5b22ac3c4a69025ffda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=88=E6=8B=89=E9=A3=8E=E7=9A=84James?= <60953754+JimZhang-lab@users.noreply.github.com> Date: Mon, 11 May 2026 09:54:42 +0800 Subject: [PATCH] Fix: Radio.Group cloneElement crashes on non-element children (#14407) ### What problem does this PR solve? `Radio.Group` in `web/src/components/ui/radio.tsx` injects the parent's `disabled` prop into each child via `React.cloneElement` with `as React.ReactElement` and no validation. This throws at runtime when a consumer passes strings, numbers, `null`, `false`, or other non-element nodes, while the cast hides the unsafe access from TypeScript. Use `React.isValidElement(child)` as a type guard before calling `cloneElement`. Non-element children pass through unchanged, and `child.props` access becomes type-checked without an `as` cast. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) --- web/src/components/ui/radio.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/web/src/components/ui/radio.tsx b/web/src/components/ui/radio.tsx index 8c9f8f59fe..8a95d53947 100644 --- a/web/src/components/ui/radio.tsx +++ b/web/src/components/ui/radio.tsx @@ -150,11 +150,12 @@ const Group = React.forwardRef( className, )} > - {React.Children.map(children, (child) => - React.cloneElement(child as React.ReactElement, { - disabled: disabled || child?.props?.disabled, - }), - )} + {React.Children.map(children, (child) => { + if (!React.isValidElement(child)) return child; + return React.cloneElement(child, { + disabled: disabled || child.props?.disabled, + }); + })} );