react-native-picker-select
react-native-picker-select copied to clipboard
in IOS, onValueChange shouldn't be triggered when only scroll item list
Is your feature request related to a problem? Please describe.
in IOS, since there is a modal picker, when the user scroll the values, but not press "Done" button, the TextInput value will also change. This will lead to unexpected strange behaviors. As the below video shows: if the UI elements will change based on the picker new selected value, when the user only scroll the item list (not press Done button), the UI elements will change dramatically, it is a different behavior with native IOS select pickers.
If I want to change the behavior, I will add the following element behaviors logic in onDonePress method, but there is also a strange behavior, because if the user scroll the list to a new value item, but not press Done button, instead the user press other space to close the picker modal, then the TextInput value is a new selected value, but other elements in the UI remains old (not change). I need carefully handle the behaviors.
Describe the solution you'd like
in IOS, if the user only scroll the item list, do not change the value, also do not trigger onValueChange, thus do not change TextInput value, only when user press "Done", the select value will be shown in TextInput.
https://github.com/lawnstarter/react-native-picker-select/assets/3772321/8d49cf0e-6df6-4b08-b5d2-c4fbec0c2235
Describe alternatives you've considered
I write a component to wrap RNPickerSelect, the code as below: introduce a internal value to store the scrolled value, only when "Done" pressed, the follow behavior will change ,but there is a strange behavior: when the user scroll the list to a new value, the TextInput will show new value, but when user press outer space to close the modal, the value in TextInput will change to its old value automatically.
` interface PickerProps extends Omit<PickerSelectProps, "onValueChange">{ showPicker?: boolean; onDoneValueCallback?: (value: any, index?: number) => void; }
export const PickerSelect : React.FC<PickerProps> = function PickerSelect(_props) {
const pickerRef = React.useRef();
const [selectedIndex, setSelectedIndex] = React.useState
React.useEffect(() => { if (showPicker){ openPicker(); }else { closePicker(); } }, [showPicker])
const onValueChangeWrapper = (value:any, index: number) => { setSelectedValue(value); setSelectedIndex(index); if(Platform.OS === 'android' && onDoneValueCallback){ onDonePressWrapper(); } }
const onDonePressWrapper = () => { if(onDoneValueCallback){ onDoneValueCallback(selectedValue, selectedIndex); } if (onDonePress){ onDonePress(); } }
const openPicker = () => { if (pickerRef.current){ if (Platform.OS === 'android') { pickerRef.current.focus(); } else { pickerRef.current.togglePicker(true) } } }
const closePicker = () => { if (pickerRef.current){ if (Platform.OS === 'android') { pickerRef.current.blur(); } else { if (pickerRef.current.state.showPicker) pickerRef.current.togglePicker(false); } } }
const onCloseWrapper = (donePressed: boolean) => { if (!donePressed && inputValue !== selectedValue){ setSelectedValue(inputValue); } if (onClose){ onClose(donePressed); } }
return ( <RNPickerSelect {..._props} value={selectedValue} onValueChange={(value, index) => onValueChangeWrapper(value, index)} ref={Platform.OS === 'ios' ? pickerRef : null} pickerProps={{ ref: Platform.OS === 'android' ? pickerRef : null }} style={pickerSelectStyles} useNativeAndroidPickerStyle={false} onDonePress={ onDonePressWrapper } onDownArrow={()=>null} onClose={onCloseWrapper} Icon={() => { return <Ionicons name="chevron-down" size={25} color="gray" />; }} /> ) } `
And the usage of this new wrapped component: <PickerSelect showPicker={isShowDaysInterval} value={daysInterval} items={ BizType.getDaysIntervalItems() } onDoneValueCallback={(value) => setDaysInterval(value)} onClose={() => setIsShowDaysInterval(false)} />
Additional details
Add any other details or screenshots about the feature request here.