picker
picker copied to clipboard
onValueChange not called on android when there is only one option
Bug
On android, with a Picker with only one available option and a selectedValue of null, pressing the option to select it doesn't trigger onValueChange.
Environment info
React native info output:
System:
OS: macOS 10.15.2
CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
Memory: 134.31 MB / 32.00 GB
Shell: 5.7.1 - /bin/zsh
Binaries:
Node: 12.10.0 - ~/.nvm/versions/node/v12.10.0/bin/node
npm: 6.13.7 - ~/Documents/teamworks/ui/mobile/node_modules/.bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
SDKs:
iOS SDK:
Platforms: iOS 13.2, DriverKit 19.0, macOS 10.15, tvOS 13.2, watchOS 6.1
IDEs:
Android Studio: 3.5 AI-191.8026.42.35.5977832
Xcode: 11.2.1/11B500 - /usr/bin/xcodebuild
npmPackages:
react: 16.12.0 => 16.12.0
react-native: 0.61.5 => 0.61.5
Library version: 1.3.0
Steps To Reproduce
- On android, render a <Picker> component with no
selectedValueand one <Picker.Item> child. - Open the <Picker> dialog and press on the item
- The dialog closes but the
onValueChangecallback is not called
Describe what you expected to happen:
- I expected
onValueChangeto be called.
Reproducible sample code
import React from 'react';
import { Picker } from '@react-native-community/picker';
const PickerExample = () => (
<Picker
onValueChange={(value, index) => { console.log(value, index); }}
>
<Picker.Item key="option-1-key" value="option-1" label="option 1" />
</Picker>
);
+1
I have got the similar issue with any items. the picker will auto select the first item by default. thus when user choose the first item, onValueChange() will NOT be called. any options to disable "select the first item by default"?
Same for iOS. However, it is possible to scroll up, then down and select an option because of the scroll bouncing
Hey, guys, have you found any workaround for this? I'm also facing a situation when onValueChange is not called for the first item
Hi @Naturalclar, do you know is there a way to avoid this bug besides explicitly setting the first item as a default value? If I get it right from the source code the problem comes from native android picker
Having the same issue as @DnEgorWeb . Did you guys find a solution for this?
If not, I would proceed with adding the first item with a placeholder label that has as value the 'undefined' string. That appears to be working:
<Picker.Item label={'--None--'} value={'undefined'}/>
On my case, I have forms with Pickers not required, so the user could leave them empty... So if they choose an item, they could need to clear the picker after that so I'm adding this before items
<Picker.Item label={''} value={''} />
and works perfectly for me
I believe this could be fix on Android, but need quite some effort
Had a quick look at the implementation:
https://github.com/react-native-picker/picker/blob/fe71dbbd3c158969744684c2c30bcd380d456cbd/android/src/main/java/com/reactnativecommunity/picker/ReactPicker.java#L37
At this line here, the native event with position value -1 should be emitted for our JS control component to handle, in case of no value selected or picker has no option items?
But neither setting selectedValue={undefined} nor giving to Picker.Item will trigger onNothingSelected callback.
If the owner may provide some guidance, I am down for helping with this.
Another related point to note is that for AdapterView.onItemSelected
This callback is invoked only when the newly selected position is different from the previously selected position or if there was no selected item.
Is it possible to use AdapterView.OnItemClickListener instead to have more picker control ?
@Naturalclar
Same issue. Did you guys find a solution for this?
Same issue. Did you guys find a solution for this?
Same issue. Did you guys find a solution for this?
onValueChange needs the value to be changed, so if there is just one item it will be selected automatically, so when selecting it the onValueChange will never be called, i am facing a similar issue when i reselect the same item, we need a new props like onValueSelected, that's would be general
We were able to somewhat work around this issue on my current project by inserting an option at the top of the list of options and using it as the picker prompt instead of using the androidPrompt prop on Picker. We style that option with a bigger font size to distinguish it as a header. This option has a bogus value, and we ignore this value in onValueChange if the option was selected.
<Picker
selectedValue={selectedValue}
onValueChange={(value) => {
if (value !== EMPTY_LABEL_VALUE) {
onChange(value);
}
}}
>
<Picker.Item
label={androidPrompt}
value={EMPTY_LABEL_VALUE}
style={styles.pickerAndroidPrompt}
/>
{options.map((option) => (
<Picker.Item
key={option.value}
label={option.label}
value={option.value}
style={styles.pickerAndroidItem}
/>
))}
</Picker>
Minor notes:
- Styling the first option with font weight did not work
- When we set the font size for the first option, there were some weird issues where other options randomly had the larger font. To work around that, we had to explicitly set the font size in the other options
This is still a big issue. onValueChange isn't fired even when specifying selectedValue to other than the first option's value. How is this not fixed?
My temporary fix is to add <Picker.Item enabled={false} /> as a first item but that looks awful.