Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/nested scroll views google places api #8256

181 changes: 98 additions & 83 deletions src/components/AddressSearch.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import _ from 'underscore';
import React, {useRef, useState} from 'react';
import PropTypes from 'prop-types';
import {LogBox} from 'react-native';
import {LogBox, ScrollView, View} from 'react-native';
import {GooglePlacesAutocomplete} from 'react-native-google-places-autocomplete';
import CONFIG from '../CONFIG';
import withLocalize, {withLocalizePropTypes} from './withLocalize';
Expand Down Expand Up @@ -117,89 +117,104 @@ const AddressSearch = (props) => {
};

return (
<GooglePlacesAutocomplete
fetchDetails
suppressDefaultStyles
enablePoweredByContainer={false}
onPress={(data, details) => {
saveLocationDetails(details);

// After we select an option, we set displayListViewBorder to false to prevent UI flickering
setDisplayListViewBorder(false);
}}
query={{
key: 'AIzaSyC4axhhXtpiS-WozJEsmlL3Kg3kXucbZus',
language: props.preferredLocale,
types: 'address',
components: 'country:us',
}}
requestUrl={{
useOnPlatform: 'web',
url: `${CONFIG.EXPENSIFY.EXPENSIFY_URL}api?command=Proxy_GooglePlaces&proxyUrl=`,
}}
textInputProps={{
InputComp: TextInput,
ref: (node) => {
if (!props.innerRef) {
return;
}

if (_.isFunction(props.innerRef)) {
props.innerRef(node);
return;
}

// eslint-disable-next-line no-param-reassign
props.innerRef.current = node;
},
label: props.label,
containerStyles: props.containerStyles,
errorText: props.errorText,
value: props.value,
isFormInput: props.isFormInput,
inputID: props.inputID,
shouldSaveDraft: props.shouldSaveDraft,
onBlur: props.onBlur,
autoComplete: 'off',
onChangeText: (text) => {
if (skippedFirstOnChangeTextRef.current) {
props.onChange({street: text});
} else {
skippedFirstOnChangeTextRef.current = true;
}

// If the text is empty, we set displayListViewBorder to false to prevent UI flickering
if (_.isEmpty(text)) {

/*
* The GooglePlacesAutocomplete component uses a VirtualizedList internally,
* and VirtualizedLists cannot be directly nested within other VirtualizedLists of the same orientation.
* To work around this, we wrap the GooglePlacesAutocomplete component with a horizontal ScrollView
* that has scrolling disabled and would otherwise not be needed
*/
<ScrollView
mananjadhav marked this conversation as resolved.
Show resolved Hide resolved
horizontal
contentContainerStyle={styles.flex1}
scrollEnabled={false}
>
<View style={styles.w100}>
mananjadhav marked this conversation as resolved.
Show resolved Hide resolved
<GooglePlacesAutocomplete
fetchDetails
suppressDefaultStyles
enablePoweredByContainer={false}
onPress={(data, details) => {
saveLocationDetails(details);

// After we select an option, we set displayListViewBorder to false to prevent UI flickering
setDisplayListViewBorder(false);
}
},
}}
styles={{
textInputContainer: [styles.flexColumn],
listView: [
!displayListViewBorder && styles.googleListView,
displayListViewBorder && styles.borderTopRounded,
displayListViewBorder && styles.borderBottomRounded,
displayListViewBorder && styles.mt1,
styles.overflowAuto,
styles.borderLeft,
styles.borderRight,
],
row: [
styles.pv4,
styles.ph3,
styles.overflowAuto,
],
description: [styles.googleSearchText],
separator: [styles.googleSearchSeparator],
}}
onLayout={(event) => {
// We use the height of the element to determine if we should hide the border of the listView dropdown
// to prevent a lingering border when there are no address suggestions.
// The height of the empty element is 2px (1px height for each top and bottom borders)
setDisplayListViewBorder(event.nativeEvent.layout.height > 2);
}}
/>
}}
query={{
key: 'AIzaSyC4axhhXtpiS-WozJEsmlL3Kg3kXucbZus',
language: props.preferredLocale,
types: 'address',
components: 'country:us',
}}
requestUrl={{
useOnPlatform: 'web',
url: `${CONFIG.EXPENSIFY.EXPENSIFY_URL}api?command=Proxy_GooglePlaces&proxyUrl=`,
}}
textInputProps={{
InputComp: TextInput,
ref: (node) => {
if (!props.innerRef) {
return;
}

if (_.isFunction(props.innerRef)) {
props.innerRef(node);
return;
}

// eslint-disable-next-line no-param-reassign
props.innerRef.current = node;
},
label: props.label,
containerStyles: props.containerStyles,
errorText: props.errorText,
value: props.value,
isFormInput: props.isFormInput,
inputID: props.inputID,
shouldSaveDraft: props.shouldSaveDraft,
onBlur: props.onBlur,
autoComplete: 'off',
onChangeText: (text) => {
if (skippedFirstOnChangeTextRef.current) {
props.onChange({street: text});
} else {
skippedFirstOnChangeTextRef.current = true;
}

// If the text is empty, we set displayListViewBorder to false to prevent UI flickering
if (_.isEmpty(text)) {
setDisplayListViewBorder(false);
}
},
}}
styles={{
textInputContainer: [styles.flexColumn],
listView: [
!displayListViewBorder && styles.googleListView,
displayListViewBorder && styles.borderTopRounded,
displayListViewBorder && styles.borderBottomRounded,
displayListViewBorder && styles.mt1,
styles.overflowAuto,
styles.borderLeft,
styles.borderRight,
],
row: [
styles.pv4,
styles.ph3,
styles.overflowAuto,
],
description: [styles.googleSearchText],
separator: [styles.googleSearchSeparator],
}}
onLayout={(event) => {
// We use the height of the element to determine if we should hide the border of the listView dropdown
// to prevent a lingering border when there are no address suggestions.
// The height of the empty element is 2px (1px height for each top and bottom borders)
setDisplayListViewBorder(event.nativeEvent.layout.height > 2);
}}
/>
</View>
</ScrollView>
);
};

Expand Down