Kevvv
Kevvv

Reputation: 4023

OnPress for React Native Google Places Autocomplete doesn't work due to its parent components

I'm trying to use the react-native-google-places-autocomplete library within my React Native app, but I'm having an issue clicking on the suggested list. Whenever I click on the Google suggested address, the list disappears and onPress doesn't grab the address. If I use the library in a component by itself without the parent components, it works perfectly fine, but only when I place the component within keyboardavoidingview or KeyboardAwareScrollView, it does not work:

This GooglePlacesInput.js component is just the standard library from the original repository:

       <GooglePlacesAutocomplete
            placeholder='Search'
            minLength={2} // minimum length of text to search
            autoFocus={false}
            returnKeyType={'search'} // Can be left out for default return key https://facebook.github.io/react-native/docs/textinput.html#returnkeytype
            keyboardAppearance={'light'} // Can be left out for default keyboardAppearance https://facebook.github.io/react-native/docs/textinput.html#keyboardappearance
            listViewDisplayed={false}   // true/false/undefined
            fetchDetails={true}
            renderDescription={row => row.description} // custom description render
            onPress={(data, details = null) => { // 'details' is provided when fetchDetails = true
                console.log(data, details);
            }}
            textInputProps={{
                onBlur,
            }}
            getDefaultValue={() => ''}

            query={{
                // available options: https://developers.google.com/places/web-service/autocomplete
                key: googleAPIKeyForAutocomplete,
                language: 'en', // language of the results
                region: "CA",
                // types: '(cities)' // default: 'geocode'
                types: '',
            }}

            styles={{
                listView: {
                    position: 'absolute',
                    top: 60,
                    left: 10,
                    right: 10,
                    backgroundColor: 'white',
                    borderRadius: 5,
                    flex: 1,
                    elevation: 3,
                    zIndex: 100,
                },
                textInputContainer: {
                    backgroundColor: 'transparent',
                    margin: 0,
                    width: '100%',
                    padding: 0,
                    borderTopWidth: 0,
                    borderBottomWidth: 0
                },
                textInput: {
                    backgroundColor: '#F9F5F4',
                    borderRadius: 50,
                    width: "100%",
                    height: height / 15,
                    padding: 20,
                },
                description: {
                    // color: '#ac879a',
                    fontWeight: '300'
                },
                predefinedPlacesDescription: {
                    color: '#1faadb'
                }
            }}

            currentLocation={true} // Will add a 'Current location' button at the top of the predefined places list
            currentLocationLabel="Current location"
            nearbyPlacesAPI='GooglePlacesSearch' // Which API to use: GoogleReverseGeocoding or GooglePlacesSearch
            GoogleReverseGeocodingQuery={{
                // available options for GoogleReverseGeocoding API : https://developers.google.com/maps/documentation/geocoding/intro
            }}
            GooglePlacesSearchQuery={{
                // available options for GooglePlacesSearch API : https://developers.google.com/places/web-service/search
                rankby: 'distance',
                type: 'food'
            }}

            GooglePlacesDetailsQuery={{
                // available options for GooglePlacesDetails API : https://developers.google.com/places/web-service/details
                fields: 'formatted_address',
            }}

            filterReverseGeocodingByTypes={['locality', 'administrative_area_level_3']} // filter the reverse geocoding results by types - ['locality', 'administrative_area_level_3'] if you want to display only cities
            predefinedPlaces={[]}
            enablePoweredByContainer={false}
            debounce={200} // debounce the requests in ms. Set to 0 to remove debounce. By default 0ms.
            renderLeftButton={() => { }}
            renderRightButton={() => { }}
        />

I'm using Formik for its parent component Form.js:

        <View style={styles.container} >
            <Formik
                initialValues={initialValues}
                onSubmit={(value, action) => submitHandler(value, action)}
                validationSchema={yup.object().shape({
                    address: yup
                        .string()
                        .min(5)
                        .required(),
                })}
            >
                {({
                    values,
                    handleChange,
                    errors,
                    setFieldTouched,
                    touched,
                    isValid,
                    handleSubmit,
                    resetForm,
                    isSubmitting,
                    }) => (
                        <View style={styles.form}>

                            <Animated.View
                                style={[styles.fieldset, addressStyle]}
                                onLayout={e => {
                                    if (addressHeight !== e.nativeEvent.layout.y) {
                                        setAddressHeight(e.nativeEvent.layout.y)
                                    }
                                }}
                            >
                                <Text style={{ marginLeft: 40, marginVertical: 5 }}>
                                    <Text style={{ color: '#FF5D4E' }}>* </Text>
                                    Address
                                    </Text>
                                <View style={styles.autoComplete}>
                                    <GooglePlacesInput
                                        onBlur={() => onBlurProps('address', setFieldTouched)}
                                    />
                                </View>
                            </Animated.View>
                            {touched.address && errors.address &&
                                <Animated.Text style={{ fontSize: 10, color: 'red' }}>{errors.address}</Animated.Text>
                            }
                            <TouchableOpacity
                                disabled={!isValid || loading || isSubmitting}
                                onPress={handleSubmit}
                                style={styles.button}
                            >
                                <Text style={styles.buttonText}>Submit</Text>
                            </TouchableOpacity>
                        </View>
                    )}
            </Formik>
        </View>

handleChange still has to be passed, but I want to first figure out the onPress situation first.

And finally, the most parent component:

        <KeyboardAwareScrollView>
            <SafeAreaView style={styles.container} >
                <ScrollView
                    keyboardShouldPersistTaps={'always'}
                    contentContainerStyle={styles.container}
                    style={{ flexGrow: 1 }}
                    showsVerticalScrollIndicator={false}
                    onLayout={e => {
                        if (heightPosition !== e.nativeEvent.layout.y) {
                            setHeightPosition(e.nativeEvent.layout.y)
                        }
                    }}
                >

                    <View style={styles.form}>
                        <Form
                            submitHandler={submitHandler}
                            loading={loading}
                            heightPosition={heightPosition}
                        />
                    </View>
                </ ScrollView>
            </SafeAreaView>
        </KeyboardAwareScrollView>

Upvotes: 17

Views: 14196

Answers (5)

log10
log10

Reputation: 54

use property

keepResultsAfterBlur: true

this will keep results pane open and it won't get away on focus change or any other event until you explicitly close the search results. the on press issue is due to focus and fading of results pane due to focus change on keyboard close event.

Upvotes: 0

Chijioke Peter
Chijioke Peter

Reputation: 9

Add this to the parent scrollViwe keyboardShouldPersistTaps={'handled'}

Upvotes: 0

Rahul Shakya
Rahul Shakya

Reputation: 1425

Please include keyboardShouldPersistTaps='always' in your parent ScrollView JSX and listViewDisplayed={false} as per the documentation:

<ScrollView
  ...
  keyboardShouldPersistTaps='always'
 >
  ...
  <GooglePlacesAutocomplete
    ...
    listViewDisplayed={false}
  />
  ...
</ScrollView>

Upvotes: 52

If you need to include this component inside a ScrolView or FlatList, remember to apply the keyboardShouldPersistTaps='handled' attribute to all ancestors ScrollView or FlatList as per documentation. Documentation Link

Upvotes: 4

Maisum Abbas
Maisum Abbas

Reputation: 359

Include this property keepResultsAfterBlur={true}.

Upvotes: 2

Related Questions