From 5bc6b37d74b40ddc0b93a3cf5a9308fd5e89df12 Mon Sep 17 00:00:00 2001 From: Bryan Lee Date: Sat, 1 Feb 2025 16:19:30 +0800 Subject: [PATCH 1/3] fix: make select.web consistent For each `` component, keep track of its `value` to `label` mapping on the `` component by passing a `MutableRefObject` that stores the mapping from `` to `` via context. On render, `` sets the label for its value. `` can then call `onValueChange` with `labelForValueRef.current[val] ?? val`, allowing feature parity with the native implementation. This approach works perfectly. Since `Item` must be rendered before it can be interacted with and emit events, this always ensures that `labelForValueRef[val]` exists before `onStrValueChange` is called. Furthermore, since the `value` and `defaultValue` prop requires `{ value: string, label: string }`, the initial render also does not have any issues. --- packages/select/src/select.web.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/select/src/select.web.tsx b/packages/select/src/select.web.tsx index 62d03fc1..5e04d970 100644 --- a/packages/select/src/select.web.tsx +++ b/packages/select/src/select.web.tsx @@ -41,14 +41,11 @@ const SelectContext = React.createContext< | (SharedRootContext & { open: boolean; onOpenChange: (open: boolean) => void; + labelForValueRef: React.MutableRefObject>; }) | null >(null); -/** - * @web Parameter of `onValueChange` has the value of `value` for the `value` and the `label` of the selected Option - * @ex When an Option with a label of Green Apple, the parameter passed to `onValueChange` is { value: 'green-apple', label: 'green-apple' } - */ const Root = React.forwardRef( ( { @@ -73,8 +70,12 @@ const Root = React.forwardRef( onOpenChangeProp?.(value); } + const labelForValueRef = React.useRef>({}); function onStrValueChange(val: string) { - onValueChange({ value: val, label: val }); + onValueChange({ + value: val, + label: labelForValueRef.current[val] ?? val, + }); } const Component = asChild ? Slot.View : View; @@ -85,6 +86,7 @@ const Root = React.forwardRef( onValueChange, open, onOpenChange, + labelForValueRef, }} > ( ({ asChild, closeOnPress = true, label, value, children, ...props }, ref) => { + const { labelForValueRef } = useRootContext(); + labelForValueRef.current[value] = label; return ( From e92545a331676ecf7e31aba9023b70a46daf4864 Mon Sep 17 00:00:00 2001 From: Bryan Lee Date: Sat, 1 Feb 2025 20:54:02 +0800 Subject: [PATCH 2/3] fix: web Select.Item `asChild` --- packages/select/src/select.web.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/select/src/select.web.tsx b/packages/select/src/select.web.tsx index 5e04d970..3c14436a 100644 --- a/packages/select/src/select.web.tsx +++ b/packages/select/src/select.web.tsx @@ -232,7 +232,12 @@ const Item = React.forwardRef( return ( - + <>{children as React.ReactNode} From f771f8f5e46f980428467f9c46471e30dcf9dfd7 Mon Sep 17 00:00:00 2001 From: Bryan Lee Date: Tue, 4 Feb 2025 22:59:44 +0800 Subject: [PATCH 3/3] fix: only write to `labelForValueRef` on init --- packages/select/src/select.web.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/select/src/select.web.tsx b/packages/select/src/select.web.tsx index 3c14436a..5e79d417 100644 --- a/packages/select/src/select.web.tsx +++ b/packages/select/src/select.web.tsx @@ -228,7 +228,9 @@ const ItemContext = React.createContext<{ const Item = React.forwardRef( ({ asChild, closeOnPress = true, label, value, children, ...props }, ref) => { const { labelForValueRef } = useRootContext(); - labelForValueRef.current[value] = label; + if (!(value in labelForValueRef.current)) { + labelForValueRef.current[value] = label; + } return (