Skip to content

Commit 28d180b

Browse files
committed
fix: make select.web consistent
For each `<Item>` component, keep track of its `value` to `label` mapping on the `<Root>` component by passing a `MutableRefObject` that stores the mapping from `<Root>` to `<Item>` via context. On render, `<Item>` sets the label for its value. `<Root>` 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.
1 parent 69405ee commit 28d180b

File tree

1 file changed

+9
-5
lines changed

1 file changed

+9
-5
lines changed

packages/select/src/select.web.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,11 @@ const SelectContext = React.createContext<
4141
| (SharedRootContext & {
4242
open: boolean;
4343
onOpenChange: (open: boolean) => void;
44+
labelForValueRef: React.MutableRefObject<Record<string, string>>;
4445
})
4546
| null
4647
>(null);
4748

48-
/**
49-
* @web Parameter of `onValueChange` has the value of `value` for the `value` and the `label` of the selected Option
50-
* @ex When an Option with a label of Green Apple, the parameter passed to `onValueChange` is { value: 'green-apple', label: 'green-apple' }
51-
*/
5249
const Root = React.forwardRef<RootRef, RootProps>(
5350
(
5451
{
@@ -73,8 +70,12 @@ const Root = React.forwardRef<RootRef, RootProps>(
7370
onOpenChangeProp?.(value);
7471
}
7572

73+
const labelForValueRef = React.useRef<Record<string, string>>({});
7674
function onStrValueChange(val: string) {
77-
onValueChange({ value: val, label: val });
75+
onValueChange({
76+
value: val,
77+
label: labelForValueRef.current[val] ?? val,
78+
});
7879
}
7980

8081
const Component = asChild ? Slot.View : View;
@@ -85,6 +86,7 @@ const Root = React.forwardRef<RootRef, RootProps>(
8586
onValueChange,
8687
open,
8788
onOpenChange,
89+
labelForValueRef,
8890
}}
8991
>
9092
<Select.Root
@@ -225,6 +227,8 @@ const ItemContext = React.createContext<{
225227

226228
const Item = React.forwardRef<ItemRef, ItemProps>(
227229
({ asChild, closeOnPress = true, label, value, children, ...props }, ref) => {
230+
const { labelForValueRef } = useRootContext();
231+
labelForValueRef.current[value] = label;
228232
return (
229233
<ItemContext.Provider value={{ itemValue: value, label: label }}>
230234
<Slot.Pressable ref={ref} {...props}>

0 commit comments

Comments
 (0)