如何在React Native中使用Google Places自动完成组件(附代码)

451 阅读16分钟

谷歌为访问其地图服务提供了大量的API,其中之一就是地点API。Places API主要通过HTTP请求为你提供有关地方的信息。你可以获得所有你需要的关于当地地址、城镇、城市、区、餐馆或任何其他地方的信息,包括其坐标。

地方API包括大量的功能,如返回与搜索字符串相关的地方列表,提供一个地方的照片,以及许多其他功能。其最常用的功能之一是自动完成服务。

使用自动完成服务,谷歌可以通过API自动填写被搜索的地方的地址或名称。因此,例如,当你的用户输入他们想要订购的餐厅名称时,你可以根据他们输入的内容向他们提供建议。

在这篇文章中,我们将看看如何在React Native中使用自动完成服务。然而,我们不需要直接使用Places API,因为一个叫做 [react-native-google-places-autocomplete](https://www.npmjs.com/package/react-native-google-places-autocomplete)的React Native包可以为我们处理这个问题。

因此,让我们看看我们如何在React Native项目中使用react-native-google-places-autocomplete 包,以及它的一些关键功能和我们如何定制它以适应我们的项目。

设置Google Places API

react-native-google-places-autocomplete 包只是一个访问Places API的媒介。如果不首先设置一个Google Cloud项目来使用Places API,它就不会发挥作用。因此,让我告诉你如何在四个步骤中做到这一点:

  1. 创建一个项目
  2. 启用计费
  3. 启用所需的API
  4. 创建一个API密钥

让我们从创建一个谷歌云项目开始。

创建一个谷歌云项目

没有谷歌云项目,我们就不能使用任何谷歌API服务。如果你还没有注册,请到谷歌云控制台去注册:

Google Cloud Console Landing Page With Welcome Message

你会进入上图所示的页面。如果你以前没有创建过项目,点击 "创建或选择项目 "按钮。一个模式将立即弹出。点击右上方的 "新项目"。

一个新的页面将加载,要求你输入项目的名称和位置--"位置 "是指该项目应属于哪个组织。你可以把位置设为 "无组织",只需为你的项目输入一个名称。

最后,点击 "创建 "来创建项目。然后,你可以选择项目或访问项目页面,查看你的项目列表。

启用Google Places API的计费功能

Google Places API不是永远免费的。谷歌采用的是随用随付的定价模式。但是你的前几个请求每个月都是免费的。

谷歌强制要求你在使用Places API之前为你的项目启用计费

前往计费页面,并选择你想启用计费的项目。将会弹出一个模式,如果你还没有,只需点击 "创建计费账户"。

按照谷歌的官方指南来创建一个计费账户。

启用所需的API

你只需要启用Places API和Geocoding API来使用react-native-google-places-autocomplete 。让我们接下来做这个。

前往你的项目仪表板,它应该看起来像这样:

Google Cloud Console Project Dashboard With Thirty-Day View And No Data Shown

如果它不像上面的图片,确保侧边栏的 "启用API和服务 "被选中。接下来点击导航栏上的 "启用API和服务"。它将带你到API库页面。

Google Cloud Console Api Library Page With Welcome Message And Search Bar

搜索 "Places API "并点击结果。下一页包含关于Places API的信息,包括价格信息和一个为你的项目启用API的按钮。点击 "启用 "按钮,这就可以了。

如果你还没有为你的项目启用计费,当你试图启用Places API时,你会被提示这样做。

之后,回到API库页面,也启用地理编码API。

创建一个API密钥

这是我们在使用该包之前必须做的最后一步。转到你的API仪表板。在左边的侧栏,选择 "证书 "选项。

Google Cloud Console Apis And Services Dashboard With Credentials Selected From Left Sidebar Menu And Reminder Message To Configure Oauth Consent Screen

点击顶部导航栏的 "创建证书",选择 "API密钥",这将为你的项目创建一个API密钥。有了这个API密钥,你只能访问你所启用的API。复制API密钥并将其保存在安全的地方。

你可能会注意到在你的API密钥旁边有一个警告图标。重要的是你要注意它。谷歌建议你将你的API密钥限制在你的应用程序中。否则,如果你不能保持你的API密钥的秘密,API密钥将对任何其他应用程序或网站无用。

这对于生产目的来说主要是有用的。由于我们只是要测试react-native-google-places-autocomplete 包的功能,所以没有必要限制密钥。

使用react-native-google-places-autocomplete

这个 [react-native-google-places-autocomplete](https://www.npmjs.com/package/react-native-google-places-autocomplete)npm包提供了一个可定制的组件来使用Google Places的自动完成服务。

它还使用了Places Details服务来提供关于搜索到的地方的更多细节,包括用户评论和坐标,以及Geocoding API来将可读地址转换为几何坐标,反之亦然。

要跟上这篇文章并看到这个包在工作,请设置一个React Native项目。

设置一个React Native项目

对于我们的React Native项目的例子,我们将为美食家创建一个应用程序来查找吃饭的地方。我们不会去看构建应用程序的每一步,因为本文的主要重点是展示一些如何使用react-native-google-places-autocomplete 包的例子。

到你的终端,运行以下程序:

npx react-native init Foodies

如果你在创建React Native项目时遇到了 [TypeError: cli.init is not a function](https://stackoverflow.com/questions/72768245/typeerror-cli-init-is-not-a-function-for-react-native)问题,卸载全局的react-native-clireact-native 。现在只重新安装全局的react-native

现在我们来安装依赖项。我们现在只需要一个依赖项:react-native-google-places-autocomplete 包:

npm install react-native-google-places-autocomplete

该包提供了一个组件,包含了我们在应用中使用和定制Places API所需的一切。让我们看看一个基本的例子:

import {GooglePlacesAutocomplete} from 'react-native-google-places-autocomplete';
import {apiKey} from './config'; // your google cloud api key

const App = () => {
  return (
    <SafeAreaView>
      <GooglePlacesAutocomplete
        placeholder="Type a place"
        query={{key: apiKey}}
      />
    </SafeAreaView>
  );
};

让我们来看看上面的例子的一些重要部分。

GooglePlacesAutocomplete 是文本输入表格,用户在其中输入一个地方的名称。当用户输入时,根据用户输入的内容建议的地方的模版将以下拉方式出现。

查询道具是唯一需要的道具;如果没有它的关键属性,自动完成包将无法使用地点API。你需要导入你的API密钥,并在这里使用它。另外,不要忘记在你的云项目上启用计费,以使用Places和Geocoding APIs。

在你的React Native项目中存储敏感信息并不是一个安全的做法。让我们讨论一下如何保护您的API密钥。

确保你的API密钥的安全

不要在React Native项目中存储你的API密钥,这一点非常重要。任何拥有你的应用包的人都可以访问你的API密钥,所以这不是一个安全的存储方法。

你可以通过使用一个服务器来存储你的API密钥来解决这个问题。这样,当用户打开应用程序时,你只需向你的服务器发出请求,获取API密钥。

也有一些措施可以保证服务器中的API密钥的安全。Brad Traversy关于保护API密钥的视频演示了如何做到这一点。

处理来自Google Places API的响应

来自Google Places API的第一组响应是自动完成的建议。react-native-google-places-autocomplete 包处理这组响应,所以我们不必担心它们。

然而,还有其他响应将由用户事件触发。例如,当建议的地址被按下时,用户的输入不会再返回任何建议(即未找到的地方)。这些响应将必须由我们来处理。

同样,自动完成包已经为我们完成了困难的部分,提供了处理这些响应的事件道具。让我们来看看一个例子:

const App = () => {
  return (
    <SafeAreaView>
      <GooglePlacesAutocomplete
        placeholder="Type a place"
        query={{key: apiKey}}
        fetchDetails={true}
        onPress={(data, details = null) => console.log(data, details)}
        onFail={error => console.log(error)}
        onNotFound={() => console.log('no results')}
      />
    </SafeAreaView>
  );
};

引入的这些新道具--onPress,onFail, 和onNotFound --是至关重要的。当使用像这样的Places API的包时,你可以使用这些道具来回答这样的问题:

  • 当用户点选一个建议时会发生什么?
  • 当搜索字符串没有结果时会发生什么?
  • 当从API中获取数据失败时会发生什么?

自动完成包提供了用props来回答这些问题的方法。我们要做的是用自定义函数来处理响应。好吧,让我们一个接一个地解决这些问题。

当用户点选一个建议时会发生什么?

当用户点选一个建议时,所选地点的信息将作为参数传入函数,然后传入onPress 道具。上面的例子中的两个参数--datadetails --都构成了关于这个地方的信息。

data 参数返回一个关于该地基本信息的对象,如描述或地址名称、国家、城市和其他细节。

如果fetchDetails 道具是falsedetails 参数将返回与数据对象相同的对象。

fetchDetails 道具默认设置为false ,但当设置为truedetails 参数会给出关于该地的更多详细信息,包括几何图形。谷歌在他们的文档中提供了一个完整的地点详细信息响应的例子。

当一个搜索字符串没有结果时,会发生什么?

很有可能,用户有时会输入一个搜索字符串,但没有收到任何结果。通过onNotFound ,我们可以在整个项目中创建没有结果的意识。然后,在你的应用程序中,你可以处理它应该如何显示,或者根据这个反应应该或不应该发生什么。

例如,我们可以停用所有其他功能(比如进入下一步订购食品),并显示一个表明没有结果的自定义消息。

另外,如果你只想提醒用户,而不对你应用中其他地方没有结果做任何特殊处理,你可以使用 [FlatList listEmptyComponent](https://reactnative.dev/docs/flatlist#listemptycomponent)道具来提醒用户没有找到结果。

你可以通过传入一个组件或一个元素来做到这一点,像这样:

const App = () => {
  return (
    <SafeAreaView>
      <GooglePlacesAutocomplete
        placeholder="Type a place"
        onPress={(data, details = null) => console.log(data, details)}
        query={{key: apiKey}}
        fetchDetails={true}
        onFail={error => console.log(error)}
        onNotFound={() => console.log('no results')}
        listEmptyComponent={() => (
          <View style={{flex: 1}}>
            <Text>No results were found</Text>
          </View>
        )}
      />
    </SafeAreaView>
  );
};

作为上述代码的结果,如果用户输入的东西没有结果,文本 "没有找到结果 "将显示在搜索栏下:

Foodie App Frontend Shown With Cursor Shown Typing In Search Bar For Unknown Place And Message Displayed Saying No Results Were Found

当从API中获取数据失败时会发生什么?

从Places API中获取数据有时也很可能导致错误。例如,Places API可能会抛出自己的错误,因为你的谷歌云项目或计费地址存在配置问题。

当API出现错误时,onFail prop会返回一个错误,无论是在使用Places API还是Geocoding API时。

你在这里可能遇到的一个非常常见的问题是,当你的项目没有启用计费或其他一些必要的计费的问题。

用预定义的地方进行搜索

你可以使用你的用户最喜欢或最常去的地方作为GooglePlacesAutocomplete 组件的预定义地方。

一个预定义的地方包含一个带有该地方信息的地址。你可以选择向用户显示地址或任何你想要的名称。

如果你使用预定义的地方,当用户关注文本输入来搜索地址时,预定义的选项将作为自动完成的建议弹出。

下面是如何将两个地点--Dominos PizzaChicken Republic --设置为favorite 类型的预定义场所:

const App = () => {
  return (
    <SafeAreaView>
      <GooglePlacesAutocomplete
        placeholder="Type a place"
        onPress={(data, details = null) => console.log(data, details)}
        query={{key: apiKey}}
        fetchDetails={true}
        onFail={error => console.log(error)}
        onNotFound={() => console.log('no results')}
        predefinedPlaces={[
          {
            type: 'favorite',
            description: 'Dominos Pizza',
            geometry: {location: {lat: 48.8152937, lng: 2.4597668}},
          },
          {
            type: 'favorite',
            description: 'Chicken Republic',
            geometry: {location: {lat: 48.8496818, lng: 2.2940881}},
          },
        ]}
      />
    </SafeAreaView>
  );
};

在上面的代码中,描述是将显示给用户的名称。当任何预定义选项被选中时,你为该地点创建的对象将被返回,并带有该地点的datadetails 参数。

这个对象并不限于只有类型、描述和几何形状。你可以添加更多关于这个地方的信息。

作为上述代码的结果,你应该看到这些favorite 预定义的地方,甚至在用户开始输入之前就出现了建议。请看下面的结果:

Foodie App Frontend Shown With Cursor Clicking Into Search Bar, Where Two Saved Places (Dominos Pizza and Chicken Republic) Showing Up Immediately, And Cursor Clicking On Dominos Pizza

使用一个自定义的文本输入组件

默认情况下,react-native-google-places-autocomplete 包使用React Native[TextInput](https://blog.logrocket.com/complete-guide-textinput-react-native/)组件来输入文本。然而,你并不拘泥于包的选择

有了textInputProps 这个道具,你可以使用任何你选择的自定义组件,比如React Native ElementsInput

import {GooglePlacesAutocomplete} from 'react-native-google-places-autocomplete';
import {apiKey} from './config'; // your google cloud api key
import {Input} from '@rneui/themed';

const App = () => {
  return (
    <SafeAreaView>
      <GooglePlacesAutocomplete
        placeholder="Type a place"
        onPress={(data, details = null) => console.log(data, details)}
        query={{key: apiKey}}
        fetchDetails={true}
        onFail={error => console.log(error)}
        onNotFound={() => console.log('no results')}
        textInputProps={{
          InputComp: Input,
        }}
      />
    </SafeAreaView>
  );
};

textInputProps 是文本输入组件的所有道具的一个对象。因此,如果你使用React Native的 ,你可以在这里使用它的特定道具。比如说。TextInput

const App = () => {
  return (
    <SafeAreaView>
      <GooglePlacesAutocomplete
        placeholder="Type a place"
        onPress={(data, details = null) => console.log(data, details)}
        query={{key: apiKey}}
        fetchDetails={true}
        onFail={error => console.log(error)}
        onNotFound={() => console.log('no results')}
        textInputProps={{
          autoFocus: true,
          blurOnSubmit: false,
        }}
      />
    </SafeAreaView>
  );
};;

上面textInputProps中使用的道具都是特定于React Native[TextInput](https://blog.logrocket.com/complete-guide-textinput-react-native/).当你使用第三方库时,也会发生同样的事情。

为你的GooglePlacesAutocomplete 组件设置样式

GooglePlacesAutocomplete 组件的默认样式是很有风格的,所以它们可能对你的应用程序来说已经足够了。

然而,你可以在默认的样式上添加一些东西,使之适合你的应用程序。你也可以完全去掉默认的样式,从头开始完全定制样式。

GooglePlacesAutocomplete 组件有一个样式道具,用于为所有组件设置样式,从文本输入到下拉菜单。让我们看看它的作用:

const App = () => {
  return (
    <SafeAreaView>
      <GooglePlacesAutocomplete
        placeholder="Type a place"
        onPress={(data, details = null) => console.log(data, details)}
        query={{key: apiKey}}
        fetchDetails={true}
        onFail={error => console.log(error)}
        onNotFound={() => console.log('no results')}
        styles={{
          container: {
            flex: 0,
          },
          description: {
            color: '#000',
            fontSize: 16,
          },
          predefinedPlacesDescription: {
            color: '#3caf50',
          },
        }}
      />
    </SafeAreaView>
  );
};

styles prop是一个使用React Native的标准样式属性和值的对象。通过styles 道具,你可以为组成GooglePlacesAutocomplete 组件的不同部分设置样式。

这些部分--如文本输入、下拉容器、每个下拉元素和其他--是GooglePlacesAutocomplete 组件的子元素。例如,对文本输入的样式设计将是这样做的:

styles={
  textInput: {
   borderColor: 'orange',
   fontSize: 20
 }
}

你应该尝试根据每个部分或属性的类型来设计其样式。例如,该组件的容器是一个视图组件,因此它应该被样式化为一个视图组件。这里有一个所有部分/属性及其元素类型的列表。

将结果限制在一个国家

可以将react-native-google-places-autocomplete 建议中显示的搜索结果限制在一个国家。这样,只有符合用户在某一国家的搜索字符串的地方才会弹出。

使用查询道具中的组件属性来指定一个国家,像这样:

query={{key: apiKey, components: 'country:us'}}

country:us 这个值只是意味着美国。它使用的是国家名称的缩写,而不是完整的名称。这里有一个支持的国家的列表

通过查询道具,你也可以提供不同语言的结果。默认的语言是英语,但通过语言属性,你可以用ISO 639-1代码指定不同的语言

query={{key: apiKey, components: 'country:us', language: 'it'}}

在上面的代码中,我们将language 属性设置为it 。这将提供意大利语的结果。如果你想提供其他语言的搜索结果,请看一下支持的语言及其代码的列表

现在,如果用户开始搜索,搜索结果将以意大利语出现,并且只显示美国境内的选项。

Foodie App Frontend With Partially Typed Search Phrase San In Search Bar And Dropdown Results Shown In Italian Located In United States

取回输入值

react-native-google-places-autocomplete 包所提供的方法之一是getAddressText 。这个方法返回用户的文本输入值。

这个方法有很多用例。例如,当搜索一个未知的地方时,以一种特殊的方式显示用户的输入,或者在搜索时发生错误时重新使用用户的最后一次输入。

要使用该包提供的任何方法,我们首先要使用React refsGooglePlacesAutocomplete 组件进行引用,像这样:

const App = () => {
  const placesRef = useRef();

  const getAddress = () => {
    console.log(placesRef.current?.getAddressText());
  };

  return (
    <SafeAreaView>
      <GooglePlacesAutocomplete
        placeholder="Type a place"
        onPress={(data, details = null) => console.log(data, details)}
        query={{key: apiKey}}
        fetchDetails={true}
        onFail={error => console.log(error)}
        onNotFound={() => console.log('no results')}
        ref={placesRef}
      />
    </SafeAreaView>
  );
};

其他可能有用的方法是:

  • setAddressText:改变文本输入的值
  • clear: 清除文本输入
  • isFocused:如果文本输入被聚焦,则返回true,如果没有则返回false。
  • getCurrentLocation:根据当前位置进行查询,以找到附近的地方。

接下来让我们探讨如何使用getCurrentLocation

获取当前位置

getCurrentLocation 方法根据用户的当前位置进行查询,以找到附近的地方。然而,这并不是这个包所提供的唯一的位置功能;它也可以用检索地方信息的同样方式获得用户的当前位置。

该软件包使用地理定位服务来寻找用户的位置,并将其作为自动完成建议的一部分。当选择时,关于用户当前位置的细节将被返回。

为了实现这一点,我们必须将currentLocation 道具设置为true

const App = () => {
  return (
    <SafeAreaView>
      <GooglePlacesAutocomplete
        placeholder="Type a place"
        onPress={(data, details = null) => console.log(data, details)}
        query={{key: apiKey}}
        fetchDetails={true}
        onFail={error => console.log(error)}
        onNotFound={() => console.log('no results')}
        currentLocation={true}
        currentLocationLabel="Your location!" // add a simple label
      />
    </SafeAreaView>
  );
};

这并不是一个完整的应用程序所要设置的全部内容。你还得安装一个地理定位服务提供商,如 [react-native-geolocation-service](https://www.npmjs.com/package/react-native-geolocation-service).

此外,你需要要求你的用户授予位置权限,以使用任何带有react-native-google-places-autocomplete 的位置服务。然而,这些具体步骤超出了本文的范围,本文特别关注react-native-google-places-autocomplete 包。

总结

在这篇文章中,我们看了如何为react-native-google-places-autocomplete 包建立一个谷歌云项目。我们还通过包的道具和方法看了大量的功能。

例如,我们看了处理响应、保护你的API密钥、设计GooglePlacesAutocomplete 组件、将结果限制在一个国家、以不同的语言显示结果、使用getAddressText 等方法、使用自定义文本输入组件,以及其他。

现在,这个包并不限于我们在这里列出的内容。你可以找到更多的道具和方法,这些道具和方法将有助于定制该包,以适应你希望在你的应用程序中使用Google Places API的方式。

我希望你玩得很开心。请在评论区告诉我你的想法。谢谢你的阅读,并祝你黑客生涯愉快。