diff --git a/src/components/AddressSearch.js b/src/components/AddressSearch.js index 6d60ec64b5c3..a8ba3ff5879c 100644 --- a/src/components/AddressSearch.js +++ b/src/components/AddressSearch.js @@ -1,7 +1,7 @@ import _ from 'underscore'; import React, {useEffect, useState, useRef} from 'react'; import PropTypes from 'prop-types'; -import {LogBox, View} from 'react-native'; +import {LogBox} from 'react-native'; import {GooglePlacesAutocomplete} from 'react-native-google-places-autocomplete'; import CONFIG from '../CONFIG'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; @@ -35,7 +35,8 @@ const defaultProps = { containerStyles: null, }; -// Do not convert to class component! setAddressText only works in functional components! +// Do not convert to class component! It's been tried before and presents more challenges than it's worth. +// Relevant thread: https://expensify.slack.com/archives/C03TQ48KC/p1634088400387400 // Reference: https://github.com/FaridSafi/react-native-google-places-autocomplete/issues/609#issuecomment-886133839 const AddressSearch = (props) => { const googlePlacesRef = useRef(); @@ -82,66 +83,72 @@ const AddressSearch = (props) => { }; return ( + { + saveLocationDetails(details); - // We use the View height to determine if we should hide the border and margin of the listView dropdown - // to prevent a lingering border when there are no address suggestions. - // The height of the input + wrapped error message is 112 pixels - { + const isTextValid = !_.isEmpty(text) && _.isEqual(text, props.value); + + // Ensure whether an address is selected already or has address value initialized. + if (!_.isEmpty(googlePlacesRef.current.getAddressText()) && !isTextValid) { + saveLocationDetails({}); + } + + // 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.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) const {height} = event.nativeEvent.layout; - return height > 112 ? setDisplayListViewBorder(true) : setDisplayListViewBorder(false); + setDisplayListViewBorder(height > 2); }} - > - saveLocationDetails(details)} - query={{ - key: 'AIzaSyC4axhhXtpiS-WozJEsmlL3Kg3kXucbZus', - language: props.preferredLocale, - types: 'address', - components: 'country:us', - }} - requestUrl={{ - useOnPlatform: 'web', - url: `${CONFIG.EXPENSIFY.URL_EXPENSIFY_COM}api?command=Proxy_GooglePlaces&proxyUrl=`, - }} - textInputProps={{ - InputComp: ExpensiTextInput, - label: props.label, - containerStyles: props.containerStyles, - errorText: props.errorText, - onChangeText: (text) => { - const isTextValid = !_.isEmpty(text) && _.isEqual(text, props.value); - - // Ensure whether an address is selected already or has address value initialized. - if (!_.isEmpty(googlePlacesRef.current.getAddressText()) && !isTextValid) { - saveLocationDetails({}); - } - }, - }} - styles={{ - textInputContainer: [styles.flexColumn], - listView: [ - 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], - }} - /> - + /> ); };