11import React , {
2- useState ,
3- useRef ,
4- useEffect ,
52 forwardRef ,
3+ useEffect ,
64 useImperativeHandle ,
5+ useRef ,
6+ useState ,
77} from 'react' ;
88import {
9- View ,
10- TextInput ,
11- FlatList ,
12- Text ,
13- TouchableOpacity ,
14- StyleSheet ,
159 ActivityIndicator ,
16- Keyboard ,
10+ FlatList ,
1711 I18nManager ,
12+ Keyboard ,
1813 Platform ,
14+ StyleSheet ,
15+ Text ,
16+ TextInput ,
17+ TouchableOpacity ,
18+ View ,
1919} from 'react-native' ;
2020
2121// Import the API functions
2222import {
23- fetchPredictions as fetchPredictionsApi ,
2423 fetchPlaceDetails as fetchPlaceDetailsApi ,
24+ fetchPredictions as fetchPredictionsApi ,
2525 generateUUID ,
2626 isRTLText ,
2727} from './services/googlePlacesApi' ;
@@ -62,6 +62,7 @@ const GooglePlacesTextInput = forwardRef(
6262 const debounceTimeout = useRef ( null ) ;
6363 const inputRef = useRef ( null ) ;
6464 const suggestionPressing = useRef ( false ) ;
65+ const skipNextFocusFetch = useRef ( false ) ;
6566
6667 const generateSessionToken = ( ) => {
6768 return generateUUID ( ) ;
@@ -97,6 +98,10 @@ const GooglePlacesTextInput = forwardRef(
9798 // Expose methods to parent through ref
9899 useImperativeHandle ( ref , ( ) => ( {
99100 clear : ( ) => {
101+ if ( debounceTimeout . current ) {
102+ clearTimeout ( debounceTimeout . current ) ;
103+ }
104+ skipNextFocusFetch . current = true ;
100105 setInputText ( '' ) ;
101106 setPredictions ( [ ] ) ;
102107 setShowSuggestions ( false ) ;
@@ -185,27 +190,26 @@ const GooglePlacesTextInput = forwardRef(
185190 if ( fetchDetails ) {
186191 // Show loading indicator while fetching details
187192 setLoading ( true ) ;
188-
189193 // Fetch the place details - Note that placeId is already in the correct format
190194 const details = await fetchPlaceDetails ( place . placeId ) ;
191-
192195 // Merge the details with the place data
193196 const enrichedPlace = details ? { ...place , details } : place ;
194-
195197 // Pass both the enriched place and session token to parent
196198 onPlaceSelect ?. ( enrichedPlace , sessionToken ) ;
197199 setLoading ( false ) ;
198200 } else {
199201 // Original behavior when fetchDetails is false
200202 onPlaceSelect ?. ( place , sessionToken ) ;
201203 }
202-
203204 // Generate a new token after a place is selected
204205 setSessionToken ( generateSessionToken ( ) ) ;
205206 } ;
206207
207- // Show suggestions on focus if text length > minCharsToFetch
208208 const handleFocus = ( ) => {
209+ if ( skipNextFocusFetch . current ) {
210+ skipNextFocusFetch . current = false ;
211+ return ;
212+ }
209213 if ( inputText . length >= minCharsToFetch ) {
210214 fetchPredictions ( inputText ) ;
211215 setShowSuggestions ( true ) ;
@@ -271,25 +275,6 @@ const GooglePlacesTextInput = forwardRef(
271275 ) ;
272276 } ;
273277
274- const renderSuggestions = ( ) => {
275- if ( ! showSuggestions || predictions . length === 0 ) return null ;
276-
277- return (
278- < View style = { [ styles . suggestionsContainer , style . suggestionsContainer ] } >
279- < FlatList
280- data = { predictions }
281- renderItem = { renderSuggestion }
282- keyExtractor = { ( item ) => item . placePrediction . placeId }
283- keyboardShouldPersistTaps = "always"
284- style = { style . suggestionsList }
285- scrollEnabled = { true }
286- bounces = { false }
287- nestedScrollEnabled = { true }
288- />
289- </ View >
290- ) ;
291- } ;
292-
293278 const getPadding = ( ) => {
294279 const physicalRTL = I18nManager . isRTL ;
295280 const clearButtonPadding = showClearButton ? 75 : 45 ;
@@ -357,6 +342,10 @@ const GooglePlacesTextInput = forwardRef(
357342 < TouchableOpacity
358343 style = { [ styles . clearButton , getIconPosition ( 12 ) ] }
359344 onPress = { ( ) => {
345+ if ( debounceTimeout . current ) {
346+ clearTimeout ( debounceTimeout . current ) ;
347+ }
348+ skipNextFocusFetch . current = true ;
360349 setInputText ( '' ) ;
361350 setPredictions ( [ ] ) ;
362351 setShowSuggestions ( false ) ;
@@ -376,7 +365,7 @@ const GooglePlacesTextInput = forwardRef(
376365 </ TouchableOpacity >
377366 ) }
378367
379- { /* Loading indicator - position adjusts based on showClearButton */ }
368+ { /* Loading indicator */ }
380369 { ( loading || detailsLoading ) && showLoadingIndicator && (
381370 < ActivityIndicator
382371 style = { [ styles . loadingIndicator , getIconPosition ( 45 ) ] }
@@ -385,7 +374,23 @@ const GooglePlacesTextInput = forwardRef(
385374 />
386375 ) }
387376 </ View >
388- { renderSuggestions ( ) }
377+ { /* Suggestions */ }
378+ { showSuggestions && predictions . length > 0 && (
379+ < View
380+ style = { [ styles . suggestionsContainer , style . suggestionsContainer ] }
381+ >
382+ < FlatList
383+ data = { predictions }
384+ renderItem = { renderSuggestion }
385+ keyExtractor = { ( item ) => item . placePrediction . placeId }
386+ keyboardShouldPersistTaps = "always"
387+ style = { style . suggestionsList }
388+ scrollEnabled
389+ bounces = { false }
390+ nestedScrollEnabled
391+ />
392+ </ View >
393+ ) }
389394 </ View >
390395 ) ;
391396 }
0 commit comments