npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

react-native-google-places-textinput

v0.9.1

Published

A customizable React Native TextInput component for Google Places Autocomplete using the Places API (New)

Downloads

22,838

Readme

React Native Google Places Autocomplete TextInput

A customizable React Native TextInput component for Google Places Autocomplete using the Places API (New)

Features

  • Fully customizable UI
  • Debounced search
  • Clear button (x)
  • Loading indicator
  • Keyboard-aware
  • Custom place types filtering
  • RTL support
  • Multi-language support
  • Session token support for reduced billing costs
  • Extended place details fetching (Optional)
  • Compatible with both Expo and non-Expo projects
  • Works with Expo Web
  • Supports all TextInput props (autoCapitalize, keyboardType, etc.)
  • Control suggestion text display (lines, ellipsis)

Preview

Installation

npm install react-native-google-places-textinput
# or
yarn add react-native-google-places-textinput

Note: This package is written in TypeScript and works seamlessly with both Expo and non-Expo React Native projects with no additional configuration required.

Prerequisites

  1. Enable the Places API (New) in your Google Cloud Project

    • This component specifically requires the new Places API (New), not the legacy Places API
    • In the Google Cloud Console, go to APIs & Services > Library and search for "Places API (New)"
  2. Create an API key

    • Go to "APIs & Services" > "Credentials" and create a new API key
    • Under "API restrictions", make sure "Places API (New)" is selected

Usage

Basic Example

import GooglePlacesTextInput from 'react-native-google-places-textinput';

const YourComponent = () => {
  const handlePlaceSelect = (place) => {
    console.log('Selected place:', place);
  };

  return (
    <GooglePlacesTextInput
      apiKey="YOUR_GOOGLE_PLACES_API_KEY"
      onPlaceSelect={handlePlaceSelect}
    />
  );
};
const ConfiguredExample = () => {
  const handlePlaceSelect = (place) => {
    console.log('Selected place:', place);
  };

  return (
    <GooglePlacesTextInput
      apiKey="YOUR_GOOGLE_PLACES_API_KEY"
      onPlaceSelect={handlePlaceSelect}
      languageCode="fr"
      types={['restaurant', 'cafe']}
      includedRegionCodes={['fr', 'be']}
      minCharsToFetch={2}
    />
  );
};
const StyledExample = () => {
  const handlePlaceSelect = (place) => {
    console.log('Selected place:', place);
  };

  const customStyles = {
    container: {
      width: '100%',
      marginHorizontal: 0,
    },
    input: {
      height: 45,
      borderColor: '#ccc',
      borderRadius: 8,
    },
    suggestionsContainer: {
      backgroundColor: '#ffffff',
      maxHeight: 250,
    },
    suggestionItem: {
      padding: 15,
    },
    suggestionText: {
      main: {
        fontSize: 16,
        color: '#333',
      },
      secondary: {
        fontSize: 14,
        color: '#666',
      }
    },
    loadingIndicator: {
      color: '#999',
    },
    placeholder: {
      color: '#999',
    }
  };

  return (
    <GooglePlacesTextInput
      apiKey="YOUR_GOOGLE_PLACES_API_KEY"
      placeHolderText="Search for a place"
      onPlaceSelect={handlePlaceSelect}
      style={customStyles}
    />
  );
};
const PlaceDetailsExample = () => {
  const handlePlaceSelect = (place) => {
    console.log('Selected place:', place);
    
    // Access detailed place information 
    if (place.details) {
      console.log(place.details);
    }
  };

  const handleError = (error) => {
    console.error('API error:', error);
  };

  return (
    <GooglePlacesTextInput
      apiKey="YOUR_GOOGLE_PLACES_API_KEY"
      onPlaceSelect={handlePlaceSelect}
      onError={handleError}
      fetchDetails={true}
      detailsFields={[
        'addressComponents',
        'formattedAddress',
        'location',
        'viewport',
        'photos',
        'types'
      ]}
    />
  );
};
<ScrollView
  keyboardShouldPersistTaps="handled"
  nestedScrollEnabled={true}
>
  <Text>Fill in your address</Text>
  <GooglePlacesTextInput
    apiKey="YOUR_GOOGLE_PLACES_API_KEY"
    onPlaceSelect={handlePlaceSelect}
    scrollEnabled={false}
    nestedScrollEnabled={false}
  />
</ScrollView>
const CustomizedExample = () => {
  const handlePlaceSelect = (place) => {
    console.log('Selected place:', place);
  };

  return (
    <GooglePlacesTextInput
      apiKey="YOUR_GOOGLE_PLACES_API_KEY"
      onPlaceSelect={handlePlaceSelect}
      // TextInput props
      autoCapitalize="words"
      autoCorrect={false}
      keyboardType="default"
      returnKeyType="search"
      textContentType="location"
      // Limit suggestion text to single line with ellipsis
      suggestionTextProps={{
        mainTextNumberOfLines: 1,
        secondaryTextNumberOfLines: 1,
        ellipsizeMode: 'tail',
      }}
    />
  );
};

Props

| Prop | Type | Required | Default | Description | |------|------|----------|---------|-------------| | Basic Configuration | | apiKey | string | Yes | - | Your Google Places API key | | value | string | No | - | Controlled input value | | placeHolderText | string | No | - | Placeholder text for the input | | onPlaceSelect | (place: Place, sessionToken?: string) => void | Yes | - | Callback when a place is selected | | onTextChange | (text: string) => void | No | - | Callback when input text changes | | onFocus | (event: NativeSyntheticEvent) => void | No | - | Callback when input is focused | | onBlur | (event: NativeSyntheticEvent) => void | No | - | Callback when input is blurred | | Search Configuration | | proxyUrl | string | No | - | Custom proxy URL for API requests (Required for Expo web) | | proxyHeaders | object | No | - | Headers to pass to the proxy (ex. { Authorization: 'Bearer AUTHTOKEN' } ) | | languageCode | string | No | - | Language code (e.g., 'en', 'fr') | | includedRegionCodes | string[] | No | - | Array of region codes to filter results | | locationBias | Record<string, any> | No | - | Bias search results by location (circle or rectangle). Details | | locationRestriction | Record<string, any> | No | - | Restrict search results to location (circle or rectangle). Details | | types | string[] | No | [] | Array of place types to filter | | biasPrefixText | (text: string) => string | No | - | Optional function to modify the input text before sending to the Places API | | minCharsToFetch | number | No | 1 | Minimum characters before triggering search | | debounceDelay | number | No | 200 | Delay in milliseconds before triggering search | | Place Details Configuration | | fetchDetails | boolean | No | false | Automatically fetch place details when a place is selected | | detailsProxyUrl | string | No | null | Custom proxy URL for place details requests (Required on Expo web)| | detailsProxyHeaders | object | No | - | Headers to pass to the place details proxy (ex. { Authorization: 'Bearer AUTHTOKEN' } ) | | detailsFields | string[] | No | ['displayName', 'formattedAddress', 'location', 'id'] | Array of fields to include in the place details response. see Valid Fields | | UI Customization | | showLoadingIndicator | boolean | No | true | Show loading spinner during API requests | | showClearButton | boolean | No | true | Show clear (×) button when input has text | | forceRTL | boolean | No | - | Force RTL layout (auto-detected if not provided) | | style | GooglePlacesTextInputStyles | No | {} | Custom styling object | | hideOnKeyboardDismiss | boolean | No | false | Hide suggestions when keyboard is dismissed | | scrollEnabled | boolean | No | true | Enable/disable scrolling in the suggestions list | | nestedScrollEnabled | boolean | No | true | Enable/disable nested scrolling for the suggestions list | | suggestionTextProps | SuggestionTextProps | No | {} | Control suggestion text display (lines, ellipsis). Details | | accessibilityLabels | GooglePlacesAccessibilityLabels | No | {} | Custom accessibility labels | | TextInput Props | | ...restProps | TextInputProps | No | - | All TextInput props supported. Details | | Error Handling & Debugging | | onError | (error: any) => void | No | - | Callback when API errors occur | | enableDebug | boolean | No | false | Enable detailed console logging for troubleshooting |

Location Filtering

You can filter or bias search results based on geographic location using locationBias or locationRestriction.

Location Bias (Soft Filter)

Biases results towards a location but can still return results outside the area if they're highly relevant:

<GooglePlacesTextInput
  apiKey="YOUR_GOOGLE_PLACES_API_KEY"
  onPlaceSelect={handlePlaceSelect}
  locationBias={{
    circle: {
      center: {
        latitude: 37.7937,
        longitude: -122.3965
      },
      radius: 500.0  // meters
    }
  }}
/>

Location Restriction (Hard Filter)

Restricts results to only those within the specified area:

<GooglePlacesTextInput
  apiKey="YOUR_GOOGLE_PLACES_API_KEY"
  onPlaceSelect={handlePlaceSelect}
  locationRestriction={{
    rectangle: {
      low: { latitude: 37.7749, longitude: -122.4194 },
      high: { latitude: 37.8049, longitude: -122.3894 }
    }
  }}
/>

Supported shapes:

  • Circle: Define center (lat/lng) and radius in meters
  • Rectangle: Define southwest and northeast corners (low/high)

Use cases:

  • Show places near user's current GPS location
  • Limit results to delivery radius
  • Search within a specific neighborhood or city bounds

For more details, see Google Places API Location Biasing.

Place Details Fetching

You can automatically fetch detailed place information when a user selects a place suggestion by enabling the fetchDetails prop:

<GooglePlacesTextInput
  apiKey="YOUR_GOOGLE_PLACES_API_KEY"
  fetchDetails={true}
  detailsFields={['formattedAddress', 'location', 'viewport', 'photos']}
  onPlaceSelect={(place) => console.log(place.details)}
/>

When fetchDetails is enabled:

  1. The component fetches place details immediately when a user selects a place suggestion
  2. The details are attached to the place object passed to your onPlaceSelect callback in the details property
  3. Use the detailsFields prop to specify which fields to include in the response, reducing API costs

For a complete list of available fields, see the Place Details API documentation.

Place Details on Expo Web

Important: To use Google Places Details on Expo Web, you must provide a detailsProxyUrl prop that points to a CORS-enabled proxy for the Google Places Details API. This is required due to browser security restrictions.

<GooglePlacesTextInput
  apiKey="YOUR_GOOGLE_PLACES_API_KEY"
  fetchDetails={true}
  detailsProxyUrl="https://your-backend-proxy.com/places-details"
  onPlaceSelect={(place) => console.log(place.details)}
/>

Without a proxy, the component will still work on Expo Web for place search, but place details fetching will fail with CORS errors.

For a complete guide on setting up a proxy server for Expo Web, see Expo Web Details Proxy Guide.

Session Tokens and Billing

This component automatically manages session tokens to optimize your Google Places API billing:

  • A session token is generated when the component mounts
  • The same token is automatically used for all autocomplete requests and place details requests
  • The component automatically resets tokens after place selection, input clearing, or calling clear()

Note: This automatic session token management ensures Google treats your autocomplete and details requests as part of the same session, reducing your billing costs with no additional configuration needed.

Methods

The component exposes the following methods through refs:

  • clear(): Clears the input and suggestions
  • focus(): Focuses the input field
  • getSessionToken(): Returns the current session token
const inputRef = useRef(null);

// Usage
inputRef.current?.clear();
inputRef.current?.focus();
const token = inputRef.current?.getSessionToken();

Styling

The component accepts a style prop with the following structure:

type Styles = {
  container?: ViewStyle;
  input?: TextStyle;
  suggestionsContainer?: ViewStyle;
  suggestionItem?: ViewStyle;
  suggestionText?: {
    main?: TextStyle;
    secondary?: TextStyle;
  };
  loadingIndicator?: {
    color?: string;
  };
  placeholder?: {
    color?: string;
  };
}

For detailed styling examples, TextInput props usage, and suggestion text control, see our Styling Guide.

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT


Available on Github: https://github.com/amitpdev/react-native-google-places-textinput

Written by Amit Palomo
See other projects I built on my blog

Made with create-react-native-library