@pragadanaveen/react-native-location-autocomplete
v2.2.0
Published
A comprehensive React Native component for location autocomplete with Google Places API, featuring animated placeholders, current location, recent searches, and extensive customization options
Maintainers
Readme
React Native Location Autocomplete
A comprehensive React Native component for location autocomplete with Google Places API integration. Features animated placeholder text, current location detection, recent searches, extensive customization options, and much more.
🚀 Features
- ✅ Advanced API Optimization - Intelligent caching, request coalescing, and reduced API calls
- ✅ Animated Rotating Placeholder - Unique animated placeholder that cycles through location suggestions
- ✅ Advanced Loading States - Custom loading components, skeleton loaders, and shimmer effects
- ✅ Smooth Fade-in Animations - Results appear with elegant fade-in transitions
- ✅ Google Places API Integration - Full autocomplete and place details support
- ✅ Current Location Detection - GPS-based location detection with permissions handling
- ✅ Recent Searches - Automatically saves and displays recent location searches
- ✅ Predefined Places - Support for custom predefined locations
- ✅ Advanced Filtering - City-only filtering, country restrictions, search types
- ✅ Location Bias & Radius - Bias results based on current location with radius control
- ✅ Multiple Themes - Built-in dark, light, and default themes
- ✅ Custom Rendering - Full control over row rendering and styling
- ✅ Accessibility Support - Complete accessibility and testing support
- ✅ TypeScript Ready - Full TypeScript support (coming soon)
- ✅ Debounced Search - Optimized performance with configurable debouncing
- ✅ Error Handling - Comprehensive error handling and callbacks
- ✅ Timeout Management - Request timeout handling
📦 Installation
npm install @pragadanaveen/react-native-location-autocomplete expo-locationOptional Dependencies
# For recent searches persistence
npm install @react-native-async-storage/async-storage🎯 Basic Usage
import React from 'react';
import { LocationAutocomplete } from '@pragadanaveen/react-native-location-autocomplete';
const MyComponent = () => {
const handleLocationSelected = (location) => {
console.log('Selected location:', location);
// location object contains: { address, latitude, longitude, placeId, details }
};
return (
<LocationAutocomplete
apiKey="YOUR_GOOGLE_PLACES_API_KEY"
onLocationSelected={handleLocationSelected}
enableCurrentLocation={true}
enableRecentSearches={true}
filterCitiesOnly={true}
style={{ margin: 16 }}
/>
);
};💰 API Cost Optimization
Your package includes advanced optimizations that significantly reduce Google Places API costs:
Smart Caching System
<LocationAutocomplete
enableCaching={true} // Cache responses for 5 minutes
cacheTimeout={300000} // Customizable cache duration
maxCacheSize={100} // Limit memory usage
/>Request Coalescing
<LocationAutocomplete
enableRequestCoalescing={true} // Prevent duplicate requests
// If user types "Mumbai" quickly, only 1 API call is made
/>Skip Unnecessary Details Calls
<LocationAutocomplete
skipDetailsForPredefined={true} // Don't call details API for predefined places
predefinedPlaces={[
{ description: 'Home', latitude: 19.0760, longitude: 72.8777 },
{ description: 'Office', latitude: 19.0896, longitude: 72.8656 }
]}
/>Cost Comparison
Typical Usage Scenario: User types "Mumbai" (6 characters)
| Package | API Calls | Cost Impact | |---------|-----------|-------------| | react-native-google-places-autocomplete | 6 autocomplete + 1 details = 7 calls | Higher cost | | Your Package (optimized) | 1 autocomplete + 1 details = 2 calls | 71% cost reduction |
With Caching: Subsequent searches for "Mumbai" = 0 additional calls for 5 minutes!
🎨 Advanced Loading States
Skeleton Loader with Shimmer
<LocationAutocomplete
apiKey="YOUR_API_KEY"
onLocationSelected={handleLocationSelected}
loadingRows={4}
useShimmer={true}
enableFadeIn={true}
fadeInDuration={500}
/>Custom Loading Component
const CustomLoader = () => (
<View style={{ padding: 20, alignItems: 'center' }}>
<ActivityIndicator size="large" color="#007AFF" />
<Text style={{ marginTop: 10, color: '#666' }}>
Finding amazing places...
</Text>
</View>
);
<LocationAutocomplete
apiKey="YOUR_API_KEY"
onLocationSelected={handleLocationSelected}
loadingComponent={<CustomLoader />}
/>Animated Skeleton Cards
<LocationAutocomplete
apiKey="YOUR_API_KEY"
onLocationSelected={handleLocationSelected}
loadingRows={5}
useShimmer={true}
enableFadeIn={true}
fadeInDuration={300}
theme="dark"
/>🎨 Advanced Usage
<LocationAutocomplete
// Basic Configuration
apiKey="YOUR_API_KEY"
onLocationSelected={handleLocationSelected}
initialAddress="Mumbai, India"
// Animated Placeholder (Unique Feature!)
enableAnimatedPlaceholder={true}
placeholderOptions={['New York', 'London', 'Tokyo', 'Mumbai']}
placeholderAnimationDuration={2500}
// Current Location
enableCurrentLocation={true}
currentLocationLabel="📍 Use My Location"
requestLocationPermission={true}
// Recent Searches
enableRecentSearches={true}
maxRecentSearches={8}
recentSearchesLabel="Recent Locations"
// Search Configuration
filterCitiesOnly={false}
searchTypes={['establishment', 'geocode']}
countryCode="IN"
minLength={3}
debounceMs={400}
// Location Bias
radius={50000} // 50km
strictBounds={false}
// Predefined Places
predefinedPlaces={[
{ description: 'Home', latitude: 19.0760, longitude: 72.8777 },
{ description: 'Office', latitude: 19.0896, longitude: 72.8656 }
]}
predefinedPlacesAlwaysVisible={true}
// API Optimization (Reduces costs!)
enableCaching={true}
cacheTimeout={300000} // 5 minutes
maxCacheSize={100}
enableRequestCoalescing={true}
skipDetailsForPredefined={true}
// Advanced Loading & Animations
loadingComponent={<CustomLoader />}
loadingRows={4}
useShimmer={true}
enableFadeIn={true}
fadeInDuration={400}
// Styling & Theming
theme="dark" // 'default', 'light', 'dark'
containerStyle={{ backgroundColor: '#f5f5f5' }}
inputStyle={{ borderRadius: 12, fontSize: 18 }}
// Custom Rendering
renderRow={(data, index) => (
<CustomLocationRow data={data} index={index} />
)}
renderLeftButton={() => <SearchIcon />}
renderRightButton={() => <FilterIcon />}
// Callbacks
onFail={(error) => console.error('Location error:', error)}
onNotFound={() => console.log('No results found')}
onTimeout={() => console.log('Request timed out')}
onFocus={() => console.log('Input focused')}
onBlur={() => console.log('Input blurred')}
// Accessibility
accessibilityLabel="Location search input"
testID="location-autocomplete"
/>📋 Complete Props Reference
Basic Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| apiKey | string | required | Your Google Places API key |
| onLocationSelected | function | required | Callback when location is selected |
| initialAddress | string | "" | Initial address value |
Search & Filtering
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| filterCitiesOnly | boolean | false | Filter results to cities only |
| searchTypes | array | [] | Google Places search types |
| countryCode | string | "" | Restrict to specific country (e.g., 'IN', 'US') |
| minLength | number | 2 | Minimum characters before search |
| debounceMs | number | 300 | Debounce delay in milliseconds |
Animated Placeholder (Unique Feature!)
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| enableAnimatedPlaceholder | boolean | true | Enable rotating placeholder animation |
| placeholderOptions | array | Indian cities | Array of placeholder suggestions |
| placeholderAnimationDuration | number | 3000 | Animation cycle duration (ms) |
Current Location
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| enableCurrentLocation | boolean | false | Show current location option |
| currentLocationLabel | string | "Use Current Location" | Current location button text |
| requestLocationPermission | boolean | true | Auto-request location permissions |
Recent Searches
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| enableRecentSearches | boolean | false | Enable recent searches |
| maxRecentSearches | number | 5 | Maximum recent searches to store |
| recentSearchesLabel | string | "Recent Searches" | Recent searches header text |
Location Bias & Radius
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| radius | number | 0 | Search radius in meters |
| strictBounds | boolean | false | Strict boundary enforcement |
Predefined Places
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| predefinedPlaces | array | [] | Array of predefined locations |
| predefinedPlacesAlwaysVisible | boolean | false | Always show predefined places |
API Optimization (Reduces Costs!)
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| enableCaching | boolean | true | Cache API responses to reduce duplicate calls |
| cacheTimeout | number | 300000 | Cache expiry time in milliseconds (5 min) |
| maxCacheSize | number | 100 | Maximum number of cached responses |
| enableRequestCoalescing | boolean | true | Prevent duplicate simultaneous requests |
| skipDetailsForPredefined | boolean | true | Skip details API for predefined places |
Loading & Animation
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| loadingComponent | component | null | Custom loading component |
| loadingRows | number | 3 | Number of skeleton rows to show |
| useShimmer | boolean | false | Enable shimmer effect on skeleton |
| enableFadeIn | boolean | true | Enable fade-in animation for results |
| fadeInDuration | number | 300 | Fade-in animation duration (ms) |
Styling & Theming
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| theme | string | 'default' | Theme: 'default', 'light', 'dark' |
| style | object | {} | Input style |
| containerStyle | object | {} | Container style |
| inputStyle | object | {} | Input field style |
| listStyle | object | {} | Results list style |
| suggestionStyle | object | {} | Individual suggestion style |
| suggestionTextStyle | object | {} | Suggestion text style |
| loadingStyle | object | {} | Loading indicator style |
| currentLocationStyle | object | {} | Current location item style |
| recentSearchStyle | object | {} | Recent search item style |
Behavior
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| autoFocus | boolean | false | Auto-focus input on mount |
| clearButtonMode | string | 'while-editing' | Clear button visibility |
| returnKeyType | string | 'search' | Keyboard return key type |
| timeout | number | 20000 | Request timeout (ms) |
Custom Rendering
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| renderRow | function | null | Custom row renderer |
| renderLeftButton | function | null | Custom left button renderer |
| renderRightButton | function | null | Custom right button renderer |
| renderDescription | function | null | Custom description renderer |
Callbacks
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| onFail | function | null | Error callback |
| onNotFound | function | null | No results callback |
| onTimeout | function | null | Timeout callback |
| onPress | function | null | Item press callback |
| onFocus | function | null | Input focus callback |
| onBlur | function | null | Input blur callback |
Accessibility
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| accessibilityLabel | string | null | Accessibility label |
| testID | string | null | Test identifier |
🎨 Theming Examples
Dark Theme
<LocationAutocomplete
theme="dark"
apiKey="YOUR_API_KEY"
onLocationSelected={handleLocationSelected}
/>Custom Styling
<LocationAutocomplete
containerStyle={{
backgroundColor: '#f8f9fa',
borderRadius: 12,
padding: 16,
}}
inputStyle={{
backgroundColor: 'white',
borderColor: '#007AFF',
borderWidth: 2,
borderRadius: 8,
fontSize: 16,
}}
suggestionStyle={{
backgroundColor: 'white',
paddingVertical: 16,
}}
suggestionTextStyle={{
fontSize: 16,
color: '#333',
}}
/>🔧 Custom Rendering
Custom Row Renderer
const renderCustomRow = (data, index) => (
<TouchableOpacity style={customStyles.row}>
<Icon name="location" size={20} />
<Text style={customStyles.text}>{data.description}</Text>
<Text style={customStyles.distance}>{data.distance}</Text>
</TouchableOpacity>
);
<LocationAutocomplete
renderRow={renderCustomRow}
// ... other props
/>Custom Buttons
<LocationAutocomplete
renderLeftButton={() => (
<TouchableOpacity style={styles.iconButton}>
<Icon name="search" size={20} color="#666" />
</TouchableOpacity>
)}
renderRightButton={() => (
<TouchableOpacity style={styles.iconButton}>
<Icon name="filter" size={20} color="#666" />
</TouchableOpacity>
)}
/>🌍 Location Data Structure
The onLocationSelected callback receives a comprehensive location object:
{
address: "Mumbai, Maharashtra, India",
latitude: 19.0760,
longitude: 72.8777,
placeId: "ChIJwe1EZjDG5zsRaYxkjY_tpF0",
details: {
// Full Google Places API response
geometry: { location: { lat: 19.0760, lng: 72.8777 } },
address_components: [...],
formatted_address: "Mumbai, Maharashtra, India",
// ... other place details
}
}🚀 Performance Tips
- Use debouncing: Adjust
debounceMsbased on your needs (300-500ms recommended) - Set minimum length: Use
minLengthto avoid unnecessary API calls - Implement caching: Cache recent results to reduce API usage
- Use country restrictions: Limit search scope with
countryCode - Optimize rendering: Use
renderRowfor complex custom layouts
🔐 API Key Setup
- Go to Google Cloud Console
- Create a new project or select existing
- Enable these APIs:
- Places API
- Geocoding API (for reverse geocoding)
- Create credentials (API Key)
- Restrict the key to your app's bundle ID/package name
🆚 Comparison with react-native-google-places-autocomplete
| Feature | This Package | react-native-google-places-autocomplete | |---------|-------------|----------------------------------------| | API Cost Optimization | ✅ 70%+ cost reduction | ❌ No optimization | | Intelligent Caching | ✅ 5-minute smart cache | ❌ No caching | | Request Coalescing | ✅ Prevents duplicate calls | ❌ Multiple duplicate calls | | Animated Placeholder | ✅ Unique rotating animation | ❌ Static placeholder | | Bundle Size | 🟢 Lightweight | 🟡 Larger | | Current Location | ✅ Built-in GPS support | ✅ Supported | | Recent Searches | ✅ Built-in | ✅ Supported | | Theming | ✅ 3 built-in themes | ✅ Extensive theming | | Custom Rendering | ✅ Full control | ✅ Full control | | TypeScript | 🟡 Coming soon | ✅ Full support | | Modern React | ✅ Hooks-based | 🟡 Mixed patterns | | City Focus | ✅ Built for location apps | 🟡 General purpose |
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License
MIT © pragadanaveen
🙏 Acknowledgments
- Google Places API for location data
- React Native community for inspiration
- All contributors and users
Made with ❤️ for the React Native community
