-
Notifications
You must be signed in to change notification settings - Fork 501
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
in IOS, onValueChange shouldn't be triggered when only scroll item list #581
Comments
This is a massive issue with the iOS implementation. As soon as I press done the value goes back to being the default value if it is set with the value prop on the RNPickerSelect component. This doesn't happen if value is unset. Android works fine. With the below I can't select anything aside from "single"
|
yes, only IOS has this problem. So we need a variable to store and reflect the changed value when the user scroll the item list (if I do not use the variable for it, the item will go back the old value), but I don't want use this variable directly because the user still didn't press 'Done' button, maybe the user just wants to scroll items list to review these items. So what I can think of is: to add a new variable to store and reflect the temporary value, and when the user press 'Done', I will send the final value to the callback function. But I wonder if we can change the behavior in the component, so I don't need wrap it by myself. |
I agree with this issue. It is really not a desired behavior that the selected value gets updated before pressing on "Done" button or closing of the picker. And what I find strange is, even if you just console.log the value in onValueChange() method, the selected value still gets picked. If that is true, then why is onValueChange() required in the first place? It's like that this updating of the value is happening somehow in the module itself. |
Is there no update on this issue? The value should only change when the done button is clicked |
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.
select_issue.mov
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 =
function PickerSelect(_props) {
const pickerRef = React.useRef();
const [selectedIndex, setSelectedIndex] = React.useState()
const { onDoneValueCallback, onDonePress, showPicker=false, value, onClose } = _props;
const [selectedValue, setSelectedValue] = React.useState(value)
const inputValue = value;
// onDonePress is for IOS only api
// don't support onValueChange for in this component, for android, pass: onDoneValueCallback instead
// in order to prive a consistent api call for android and ios
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 ;
}}
/>
)
}
`
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.
The text was updated successfully, but these errors were encountered: