react-nativeexporeact-google-autocomplete

GooglePlacesAutocomplete selection not working with Slider


In expo/react-native, I have this component LocationAutocomplete using GooglePlacesAutocomplete:

import React, { useEffect, useRef } from 'react';
import { Alert } from 'react-native';
import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';

import config from '../config'; 
import colors from '../styles/colors';

const LocationAutocomplete = ({ setBirthLocation, keepListContainer=false, customStyles = {}, birthLocation = null }) => {

  const autocompleteRef = useRef(null);

  const handleLocationSelect = (data, details = null) => {
    if (details) {
      const input_address = details.formatted_address;
      const countryComponent = details.address_components.find(component => component.types.includes('country'));
      const cityComponent = details.address_components.find(component => component.types.includes('locality'));

      const country = countryComponent ? countryComponent.long_name : '';
      const city = cityComponent ? cityComponent.short_name : '';
      const latitude = details.geometry.location.lat;
      const longitude = details.geometry.location.lng;
      const utc_offset_minutes = details.utc_offset;

      if (!city) {
        Alert.alert('Invalid Selection', 'Please select a valid city.');
        return;
      }

      setBirthLocation({
        input_address,
        country,
        city,
        latitude,
        longitude,
        utc_offset_minutes,
      });
    } else {
      Alert.alert('Invalid Selection', 'Please select a valid location.');
    }
  };

  useEffect(() => {
    if (birthLocation) {
      autocompleteRef.current?.setAddressText(birthLocation.input_address);
    }
  }, [birthLocation]);

  return (
    <GooglePlacesAutocomplete
      placeholder="Start typing a location..."
      onPress={handleLocationSelect}
      ref={autocompleteRef}
      query={{ key: config.googleApiKey }}
      disableScroll={true}
      fetchDetails={true}
      enablePoweredByContainer={false}
      keepResultsAfterBlur={keepListContainer}
      textInputProps={{
        placeholderTextColor: colors.whitePlaceholder,
      }}
      styles={{
        textInputContainer: {
          width: '100%',
          alignSelf: 'center',
          marginTop: 5,
          ...customStyles.textInputContainer,
        },
        textInput: {
          height: 45,
          color: 'white',
          fontSize: 16,
          backgroundColor: colors.easyBlackInput,
          borderRadius: 0,
          fontFamily: 'Futura',
          ...customStyles.textInput,
        },
        listView: {
          width: '100%',
          alignSelf: 'center',
          ...customStyles.listView,
        },
        ...customStyles,
      }}
    />
  );
};

It's working good except when I use it in a Slider, it's correctly opening the keyboard, the user can type, but when the user clicks one of the proposition of the drop down, it doesn't write the selected line and it closes the container. The only work around I have at the moment is to keepListContainer={true} but it's very confusing for the user.

BirthLocationScreen

const BirthLocationScreen = ({ onNext, onBack }) => {
  
  const [birthLocation, setBirthLocation] = useState({
    input_address: '',
    country: '',
    city: '',
    latitude: null,
    longitude: null,
    utc_offset_minutes: null
  });

  // useEffect(() => {
  //   console.log(birthLocation);
  // }, [birthLocation]); 

  return (
    <View style={styles.container}>
      <ChevronLeftButton onPress={() => onBack()} showBackText={true} />
      <KeyboardAwareScrollView style={styles.scrollView} keyboardShouldPersistTaps='handled'>
        <Text style={globalStyles.onBoardingTitle}>Where were you born?</Text>
        <Text style={globalStyles.onBoardingSubTitle}>
          Required to calculate celestial locations.
        </Text>
        <LocationAutocomplete
          setBirthLocation={setBirthLocation}
          keepListContainer={true}
          customStyles={{textInput: styles.textInput}}
        />
      </KeyboardAwareScrollView>

      <BottomButton
        style={globalStyles.buttonBottomPosition}
        title="Continue"
        onPress={() => {
          if (birthLocation.input_address) {
            saveUserData('userBirthLocation', birthLocation, stringify = true);
            onNext();
          } else {
            Alert.alert('Please select a location', 'It will help us creating your natal chart.');
          }
        }}
      />
    </View>
  );
};

Onboarding Slider

    <View style={styles.container}>
      <Swiper
        loop={false}
        showsPagination={true}
        index={0}
        scrollEnabled={false}
        ref={swiperRef}
        activeDotColor="white"
        style={styles.swiper}
      // paginationStyle={{ top: "-80%" }}
      >
        <GenderScreen onNext={goToNextSlide} />
        <NameScreen onNext={goToNextSlide} onBack={goToPreviousSlide} />
        <BirthDateScreen onNext={goToNextSlide} onBack={goToPreviousSlide} />
        <BirthLocationScreen onNext={goToNextSlide} onBack={goToPreviousSlide} />
        <BirthTimeScreen onBack={goToPreviousSlide} />
      </Swiper>
    </View>

Solution

  • Added keyboardShouldPersistTaps="handled" to the Swiper props.