You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需原生代码,能否用Google Places Web API实现Uber克隆的地址预测与地图更新?

Can I build Uber-like address autocomplete + map update with just Google Places Web API (no native code)?

Absolutely! You can absolutely build this address autocomplete and map update functionality without touching any native code using just the Google Places Web API—perfect for your Uber clone project, especially if you’re not comfortable with native React Native modifications. Here’s how to pull it off:

Step 1: Implement Address Predictions (Autocomplete)

Instead of relying on native wrapper libraries, you’ll directly call the Places Web API from your React Native code:

  • Use the Place Autocomplete endpoint (/place/autocomplete/json) to fetch real-time predictions as the user types.
  • Add a debounce to your input handler to avoid spamming the API with every keystroke (aim for 300-500ms delay).
  • Render the returned predictions in a dropdown list below your text input.

Step 2: Update the Map When a Place is Selected

Once the user picks a prediction:

  • Grab the place_id from the selected result.
  • Call the Place Details endpoint (/place/details/json) to fetch the exact latitude/longitude of the location.
  • Pass these coordinates to your React Native map component (like react-native-maps) to update the map region and add a marker.

Example Code Snippet

Here’s a simplified working example to get you started:

import React, { useState, useCallback } from 'react';
import { TextInput, FlatList, Text, TouchableOpacity, View } from 'react-native';
import MapView, { Marker } from 'react-native-maps';
import { debounce } from 'lodash';

// Replace with your Google Cloud API key (enable Places API first!)
const GOOGLE_API_KEY = 'YOUR_API_KEY';

export default function UberCloneSearch() {
  const [inputText, setInputText] = useState('');
  const [predictions, setPredictions] = useState([]);
  const [selectedPlace, setSelectedPlace] = useState(null);

  // Debounced function to fetch place predictions
  const fetchPredictions = useCallback(debounce(async (text) => {
    if (!text.trim()) {
      setPredictions([]);
      return;
    }
    try {
      const response = await fetch(
        `https://maps.googleapis.com/maps/api/place/autocomplete/json?input=${encodeURIComponent(text)}&key=${GOOGLE_API_KEY}`
      );
      const data = await response.json();
      setPredictions(data.status === 'OK' ? data.predictions : []);
    } catch (error) {
      console.error('Failed to fetch predictions:', error);
      setPredictions([]);
    }
  }, 300), []);

  const handleInputChange = (text) => {
    setInputText(text);
    fetchPredictions(text);
  };

  const handlePlaceSelect = async (place) => {
    setInputText(place.description);
    setPredictions([]);
    
    // Fetch coordinates for the selected place
    try {
      const response = await fetch(
        `https://maps.googleapis.com/maps/api/place/details/json?place_id=${place.place_id}&key=${GOOGLE_API_KEY}`
      );
      const data = await response.json();
      if (data.status === 'OK') {
        const { lat, lng } = data.result.geometry.location;
        setSelectedPlace({ name: place.description, lat, lng });
      }
    } catch (error) {
      console.error('Failed to fetch place details:', error);
    }
  };

  return (
    <View style={{ flex: 1 }}>
      {/* Search Input */}
      <TextInput
        style={{
          height: 50,
          borderWidth: 1,
          borderColor: '#ccc',
          paddingHorizontal: 10,
          margin: 10,
          borderRadius: 8,
          backgroundColor: 'white',
        }}
        placeholder="Enter your destination"
        value={inputText}
        onChangeText={handleInputChange}
      />

      {/* Predictions Dropdown */}
      {predictions.length > 0 && (
        <FlatList
          style={{
            position: 'absolute',
            top: 70,
            left: 10,
            right: 10,
            backgroundColor: 'white',
            borderRadius: 8,
            shadowColor: '#000',
            shadowOffset: { width: 0, height: 2 },
            shadowOpacity: 0.1,
            shadowRadius: 4,
            elevation: 3,
            zIndex: 100,
          }}
          data={predictions}
          keyExtractor={(item) => item.place_id}
          renderItem={({ item }) => (
            <TouchableOpacity
              onPress={() => handlePlaceSelect(item)}
              style={{ padding: 15, borderBottomWidth: 1, borderBottomColor: '#f0f0f0' }}
            >
              <Text>{item.description}</Text>
            </TouchableOpacity>
          )}
        />
      )}

      {/* Map View */}
      <MapView
        style={{ flex: 1, marginTop: predictions.length > 0 ? 200 : 0 }}
        region={selectedPlace ? {
          latitude: selectedPlace.lat,
          longitude: selectedPlace.lng,
          latitudeDelta: 0.01,
          longitudeDelta: 0.01,
        } : {
          // Default region (e.g., San Francisco)
          latitude: 37.78825,
          longitude: -122.4324,
          latitudeDelta: 0.0922,
          longitudeDelta: 0.0421,
        }}
      >
        {selectedPlace && (
          <Marker
            coordinate={{ latitude: selectedPlace.lat, longitude: selectedPlace.lng }}
            title={selectedPlace.name}
          />
        )}
      </MapView>
    </View>
  );
}

Key Notes

  • API Setup: Make sure your Google Cloud project has the Places API enabled, and your API key has the correct restrictions (e.g., limit to your app’s bundle ID).
  • Dependencies: You’ll need to install react-native-maps (for the map) and lodash (for debouncing) via npm/yarn—no native code changes required beyond react-native-maps’s standard setup (which is minimal).
  • Cost: Keep an eye on Google’s Places API pricing to avoid unexpected charges, especially if your app gets high traffic.

内容的提问来源于stack exchange,提问作者Hendry Lim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:37:10