picker icon indicating copy to clipboard operation
picker copied to clipboard

onValueChange not called on android when there is only one option

Open sam1463 opened this issue 5 years ago • 14 comments

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

  1. On android, render a <Picker> component with no selectedValue and one <Picker.Item> child.
  2. Open the <Picker> dialog and press on the item
  3. The dialog closes but the onValueChange callback is not called

Describe what you expected to happen:

  1. I expected onValueChange to 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>
);

sam1463 avatar Feb 25 '20 21:02 sam1463

+1

orzhtml avatar Apr 08 '20 04:04 orzhtml

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"?

bill2004158 avatar May 15 '20 07:05 bill2004158

Same for iOS. However, it is possible to scroll up, then down and select an option because of the scroll bouncing

CyxouD avatar May 25 '20 15:05 CyxouD

Hey, guys, have you found any workaround for this? I'm also facing a situation when onValueChange is not called for the first item

DnEgorWeb avatar Jun 22 '20 12:06 DnEgorWeb

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

DnEgorWeb avatar Jun 22 '20 12:06 DnEgorWeb

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'}/>

villanuevadani avatar Aug 19 '20 15:08 villanuevadani

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

ayozebarrera avatar Aug 31 '20 09:08 ayozebarrera

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

Roytangrb avatar Jan 07 '21 10:01 Roytangrb

Same issue. Did you guys find a solution for this?

v-kryuchkov avatar Mar 26 '21 08:03 v-kryuchkov

Same issue. Did you guys find a solution for this?

marlti7 avatar May 12 '21 06:05 marlti7

Same issue. Did you guys find a solution for this?

csamet07 avatar Jun 07 '21 14:06 csamet07

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

wissemContractor avatar Jun 16 '21 10:06 wissemContractor

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

stevehanson avatar Oct 14 '21 21:10 stevehanson

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.

Livijn avatar Apr 28 '22 11:04 Livijn