Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/@react-stately/select/src/useSelectState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export interface SelectState<T, M extends SelectionMode = 'single'> extends List
readonly defaultValue: ValueType<M>,

/** Sets the select value. */
setValue(value: Key | Key[] | null): void,
setValue(value: Key | readonly Key[] | null): void,

/**
* The value of the first selected item.
Expand Down Expand Up @@ -88,7 +88,7 @@ export function useSelectState<T extends object, M extends SelectionMode = 'sing
let value = useMemo(() => {
return props.value !== undefined ? props.value : (selectionMode === 'single' ? props.selectedKey : undefined) as ValueType<M>;
}, [props.value, props.selectedKey, selectionMode]);
let [controlledValue, setControlledValue] = useControlledState<Key | Key[] | null>(value, defaultValue, props.onChange as any);
let [controlledValue, setControlledValue] = useControlledState<Key | readonly Key[] | null>(value, defaultValue, props.onChange as any);
// Only display the first selected item if in single selection mode but the value is an array.
let displayValue = selectionMode === 'single' && Array.isArray(controlledValue) ? controlledValue[0] : controlledValue;
let setValue = (value: Key | Key[] | null) => {
Expand Down
5 changes: 3 additions & 2 deletions packages/@react-types/select/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ import {
} from '@react-types/shared';

export type SelectionMode = 'single' | 'multiple';
export type ValueType<M extends SelectionMode> = M extends 'single' ? Key | null : Key[];
export type ValueType<M extends SelectionMode> = M extends 'single' ? Key | null : readonly Key[];
export type ChangeValueType<M extends SelectionMode> = M extends 'single' ? Key | null : Key[];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if we can remove the null from the change value type for single selection. We already have the disallowEmptySelection option set.

disallowEmptySelection: selectionMode === 'single',

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately can't remove it, there is a way to get null out of this, which is to use the context to setValue(null), which acts like resetting the whole state back to the initial state where nothing is selected.

function SelectClearButton() {
  /*- begin highlight -*/
  let state = React.useContext(SelectStateContext);
  /*- end highlight -*/
  return (
    <Button
      // Don't inherit behavior from Select.
      slot={null}
      style={{fontSize: 'small', marginTop: 6, padding: 4}}
      onPress={() => state?.setValue(null)}>
      Clear
    </Button>
  );
}

Yes, it's a little weird. But we documented it at one point, so I think we've decided we were stuck with it for a while.

type ValidationType<M extends SelectionMode> = M extends 'single' ? Key : Key[];

export interface SelectProps<T, M extends SelectionMode = 'single'> extends CollectionBase<T>, Omit<InputBase, 'isReadOnly'>, ValueBase<ValueType<M>>, Validation<ValidationType<M>>, HelpTextProps, LabelableProps, TextInputBase, FocusableProps {
export interface SelectProps<T, M extends SelectionMode = 'single'> extends CollectionBase<T>, Omit<InputBase, 'isReadOnly'>, ValueBase<ValueType<M>, ChangeValueType<M>>, Validation<ValidationType<M>>, HelpTextProps, LabelableProps, TextInputBase, FocusableProps {
/**
* Whether single or multiple selection is enabled.
* @default 'single'
Expand Down