Reputation: 4023
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
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
Reputation: 9
Add this to the parent scrollViwe keyboardShouldPersistTaps={'handled'}
Upvotes: 0
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
Reputation: 817
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