Skip to content

(FIX) onValueChange being called twice #369

@Deckstar

Description

@Deckstar

Hello! 🙂

As some other users have noted, it seems that there is often an issue with this library where the "onValueChange" function is called twice. (For example, see issues #311 , #265 , #242 , #180 , #112 ).

In my case, I had this issue while using the component with reduxForm, which made the component either: 1) bounce back to the previous value every time I tried to select something on iOS, or 2) simply not change anything when selecting a value on Android. (Probably the same thing was happening under the hood, the Android picker just wasn't animated).

I have solved the issue in my local app by replacing getDerivedStateFromProps with compononentDidUpdate in the index.js file of the react-native-picker-select component. I have opened a pull request ( #368 ) with the hope that it may solve others' problems as well.

Describe the bug

The picker doesn't work because the onValueChange call back is called twice, making the selected value reset itself each time. (See GIF).

To Reproduce

Create a custom Field component with the Redux Form library (such as the one I added below). Try to select a value on iOS or Android.

Expected behavior

New value is selected with no problems.

Actual behavior

Value is selected, but the onValueChange callback is immediately called again, forcing the value to go back to its previous state.

Screenshots

ezgif-2-1997a59fb427

Additional details

  • Device: iPhone11 simulator (or Android through AVD)
  • OS: iOS14 (or Android)
  • react-native-picker-select version: latest
  • react-native version: 0.63
  • expo sdk version: n/a

Reproduction and/or code sample

export class PickerField extends PureComponent<BaseFieldProps & PickerSelectProps> {
  getStyle = (params: { active?: boolean, dirty: boolean, invalid: boolean, style: any }) => {
    const { active, dirty, invalid, style } = params;

    let styleObj = { ...styles.inputContainerStyle, ...{ color: Colors.black } };

    if (active) {
      styleObj = { ...styleObj, ...styles.inputBoxActive }
    }
    if (dirty) {
      styleObj = { ...styleObj, ...styles.inputBoxDirty }
    }
    if (invalid) {
      styleObj = { ...styleObj, ...styles.invalidBox }
    }
    if (style) {
      styleObj = { ...styleObj, ...style, }
    }

    return styleObj;
  }

  renderPicker = ({ input, meta }: WrappedFieldProps) => {
    const { items, style, ...rest } = this.props;

    const { onChange, value } = input;
    const { invalid, active, dirty, } = meta;

    const combinedStyle = this.getStyle({ active, dirty, invalid, style });

    return (
      <RNPickerSelect
        value={value}
        items={items}
        onValueChange={onChange}
        style={{
          chevron: { display: 'none' },
          inputIOS: combinedStyle,
          inputAndroid: combinedStyle,
          iconContainer: {
            top: '50%',
            right: '2%',
            transform: [{ translateY: -(1 / 2) * this.iconHeight }],
          },
        }}
        // placeholder={{ label: I18n.t("SelectAnItem") }}
        useNativeAndroidPickerStyle={false}
        {...rest}
      />
    )
  }

  render() {

    const { name, validate } = this.props;
    return (
      <Field name={name} component={this.renderPicker} validate={validate} />
    )
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions