'react-native-web picker strange behavior on web mobile

We're using react-native-web which allows for reactJS and react-native in one codebase. Form components can be tricky in getting them to work for web, mobile web and native. We're using Picker for a dropdown menu on a modal form and so far it works in full web and native but on mobile web, the drop down menu placement is above and to the side of the actual picker. Is there a way to force it to use the device selector at a certain screen size?

enter image description here

Here's an example of our reusable selector component:

import React, { useState, useEffect } from 'react'
import {
  View,
  Text,
  Platform,
  TextInputProps,
  StyleSheet,
  ViewStyle,
  StyleProp,
} from 'react-native'
import { isAndroid } from 'shared/util/style'
import { withTranslation, WithTranslation } from 'react-i18next'
// @ts-ignore
import Picker from 'shared/components/Picker'
// @ts-ignore
import Tooltip from 'shared/components/Tooltip'
import { fonts, colors, isIE } from '../util/style'

const styles = StyleSheet.create({
  container: {
    paddingTop: 10,
    paddingBottom: 6,
    width: '100%',
  },
  label: {
    ...fonts.regularSemibold,
    color: colors.black,
    marginBottom: 6,
  },
  bottomContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    paddingTop: 5,
  },
  errorText: {
    ...fonts.bodyRegular,
    color: colors.orange,
    fontWeight: '100',
  },
  picker: {
    backgroundColor: colors.white,
    borderWidth: 0,
    padding: 10,
    width: '100%',
    height: isIE ? 'auto' : 60,
    ...fonts.bodyRegular,
  },
  pickerIOS: {
    width: '100%',
  },
  pickerText: {
    ...fonts.bodyRegular,
    color: 'blue',
  },
})

type AccessibleSelectProps = TextInputProps & {
  readonly label?: string
  readonly onValueChange: any
  readonly defaultValue?: string | undefined | null | number
  readonly fieldError?: string
  readonly refToAttachToInput?: any
  readonly additionalContainerStyles?: StyleProp<ViewStyle>
  readonly inputStyle?: any
  readonly leftButtonIcon?: number
  readonly onFocus?: (event: any) => void
  readonly options: Array<{ label: string; value: string }>
  readonly selectedValue: string | number | undefined
  readonly tooltipText?: string
  readonly tooltipContent?: string
  readonly tooltipPlacement?: string
} & WithTranslation

const AccessibleSelect = ({
  onValueChange,
  selectedValue,
  defaultValue,
  fieldError,
  label,
  additionalContainerStyles,
  options,
  refToAttachToInput,
  inputStyle,
  tooltipText,
  tooltipContent,
  tooltipPlacement,
}: AccessibleSelectProps) => {
  const [borderColor, setBorderColor] = useState(colors.grey1)

  const checkError = () => {
    if (fieldError) {
      setBorderColor(colors.orange)
    }
  }

  useEffect(checkError, [fieldError])
  return (
    <View style={[styles.container, additionalContainerStyles]}>
      <View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
        <Text style={styles.label}>{label}</Text>
        <Tooltip
          text={tooltipText}
          content={tooltipContent}
          placement={tooltipPlacement}
        />
      </View>
      <Picker
        ref={refToAttachToInput}
        style={[
          Platform.OS === 'ios'
            ? styles.pickerIOS
            : [
                styles.picker,
                { borderColor, borderStyle: 'solid', borderWidth: 1 },
              ],
          inputStyle,
        ]}
        selectedValue={selectedValue}
        onValueChange={onValueChange}
        defaultValue={defaultValue && defaultValue}
        itemStyle={styles.pickerText}
        mode={isAndroid && 'dropdown'}
      >
        {options.map((o) => (
          <Picker.Item label={o.label} key={o.value} value={o.value} />
        ))}
      </Picker>
      <View
        style={[
          styles.bottomContainer,
          { justifyContent: fieldError ? 'space-between' : 'flex-end' },
        ]}
      >
        {!!fieldError && (
          <Text accessibilityLiveRegion="assertive" style={styles.errorText}>
            {fieldError}
          </Text>
        )}
      </View>
    </View>
  )
}

export default withTranslation('Login')(AccessibleSelect)

The Picker component is imported in 2 ways: 1 for native and 1 for web:

For Native:

import { Picker } from '@react-native-picker/picker'

export default Picker

For Web:

import { Picker } from 'react-native'

export default Picker


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source