如何在同一个NextJS页面上使用GoogleMap和Autocomplete?

dphi5xsq  于 2023-04-20  发布在  Go
关注(0)|答案(1)|浏览(129)

下面是我的代码:
页码

import Map from "@/components/Map";
import { grayMid } from "@/theme/colors";
import { GoogleCoords } from "@/typings";
import { LegacyRef, useRef, useState } from "react";
import Autocomplete from "react-google-autocomplete";

const AddGolfCoursePage = () => {
    const [center, setCenter] = useState<GoogleCoords>({
        lat: 0,
        lng: 0,
    });
    const [zoom, setZoom] = useState(2);
    const [listOfCoordinates, setListOfCoordinates] = useState<GoogleCoords[]>(
        []
    );

    const searchRef: LegacyRef<HTMLInputElement> = useRef(null);

    const handleClickGolfCourse = (place: google.maps.places.PlaceResult) => {
        const lat: any = place.geometry?.location?.lat();
        const lng: any = place.geometry?.location?.lng();
        setCenter({ lat, lng });
        setZoom(16);
    };

    const handleClearSearchInput = () => {
        if (searchRef.current) {
            searchRef.current.value = "";
        }
    };

    const handleOnRightClick = (e: google.maps.MapMouseEvent) => {
        const coords: GoogleCoords = e.latLng?.toJSON() || { lat: 0, lng: 0 };
        setListOfCoordinates((prev) => [...prev, coords]);
    };

    const handleOnDragEndMarker = (
        e: google.maps.MapMouseEvent,
        index: number
    ) => {
        const newCoords: GoogleCoords = e.latLng?.toJSON() || {
            lat: 0,
            lng: 0,
        };
        const coordsCopy = listOfCoordinates.slice(0);
        coordsCopy.splice(index, 1, newCoords);
        setListOfCoordinates(coordsCopy);
    };

    return (
        <div style={{ padding: 8 }}>
            {/* Search Input */}
            <Autocomplete
                ref={searchRef}
                apiKey="API_KEY"
                style={{
                    width: "50%",
                    marginBottom: 8,
                    paddingInline: 8,
                    paddingBlock: 4,
                    borderRadius: 8,
                    zIndex: 100,
                }}
                options={{
                    types: [],
                    componentRestrictions: { country: "us" },
                }}
                onPlaceSelected={(place) => {
                    handleClickGolfCourse(place);
                }}
            />
            <button
                onClick={handleClearSearchInput}
                className="active:opacity-50"
                style={{
                    marginLeft: 8,
                    borderRadius: 8,
                    paddingInline: 8,
                    backgroundColor: grayMid,
                    paddingBlock: 4,
                }}>
                Clear
            </button>
            {/* Map */}
            <Map
                center={center}
                zoom={zoom}
                listOfCoordinates={listOfCoordinates}
                handleOnRightClick={handleOnRightClick}
                handleOnDragEndMarker={handleOnDragEndMarker}
            />
        </div>
    );
};

export default AddGolfCoursePage;

组件

import { GoogleCoords } from "@/typings";
import { GoogleMap, useJsApiLoader, Marker } from "@react-google-maps/api";

interface Props {
    center: GoogleCoords;
    zoom: number;
    listOfCoordinates: GoogleCoords[];
    handleOnRightClick: any;
    handleOnDragEndMarker: any;
}

const Map = ({
    center,
    zoom,
    listOfCoordinates,
    handleOnRightClick,
    handleOnDragEndMarker,
}: Props) => {
    const { isLoaded } = useJsApiLoader({
        id: "google-map-script",
        googleMapsApiKey: "API_KEY",
    });

    return (
        <>
            {isLoaded && (
                <GoogleMap
                    mapContainerStyle={{ width: 600, height: 600 }}
                    options={{
                        streetViewControl: false,
                        mapTypeId: "satellite",
                    }}
                    center={center}
                    zoom={zoom}
                    tilt={0}
                    onRightClick={handleOnRightClick}
                    clickableIcons={false}>
                    {listOfCoordinates.map((point, index) => (
                        <Marker
                            draggable={true}
                            onDragEnd={(e) => handleOnDragEndMarker(e, index)}
                            key={index}
                            position={point}
                        />
                    ))}
                </GoogleMap>
            )}
        </>
    );
};

export default Map;

下面是错误:您在此页面上多次包含Google Maps JavaScript API。这可能会导致意外错误。
我需要这两件事在同一页上。我能做些什么来完成这一点?谢谢。
这是我写的一堆随机的东西,这样它就可以让我的帖子被发表。当我有这么高的代码与文本比率时,它不会让我发表帖子。希望这篇文章能够把这个比率降低一点,这样我就可以在几个小时的努力之后最终弄清楚如何做到这一点。ChatGPT是一个绝对的笑话。我需要一个聪明的人来证明人工智能不会取代我们所有人。谢谢。

hujrc8aj

hujrc8aj1#

来自react-google-autocompleteAutocomplete组件和来自@react-google-maps/apiGoogleMap组件都独立加载Google Maps JavaScript API。
要解决此问题,可以尝试使用react-places-autocomplete包中的usePlacesAutocomplete钩子

npm install react-places-autocomplete

修改AddGolfCoursePage组件以使用PlacesAutocomplete组件:

import { GoogleMap, useJsApiLoader, Marker } from "@react-google-maps/api";
import PlacesAutocomplete, { geocodeByAddress, getLatLng } from "react-places-autocomplete";

const AddGolfCoursePage = () => {
  // Your existing state variables and functions here
  const [address, setAddress] = useState("");

  // Handle place selection
  const handleSelect = async (address) => {
    setAddress(address);
    const results = await geocodeByAddress(address);
    const latLng = await getLatLng(results[0]);
    handleClickGolfCourse(latLng);
  };

  // Modify your return statement
  return (
    <div style={{ padding: 8 }}>
      {/* Search Input */}
      <PlacesAutocomplete
        value={address}
        onChange={setAddress}
        onSelect={handleSelect}
        searchOptions={{
          types: [],
          componentRestrictions: { country: "us" },
        }}
      >
        {({ getInputProps, suggestions, getSuggestionItemProps, loading }) => (
          <div>
            <input
              {...getInputProps({
                placeholder: "Search Places ...",
                className: "location-search-input",
                style: {
                  width: "50%",
                  marginBottom: 8,
                  paddingInline: 8,
                  paddingBlock: 4,
                  borderRadius: 8,
                  zIndex: 100,
                },
              })}
            />
            <div className="autocomplete-dropdown-container">
              {loading && <div>Loading...</div>}
              {suggestions.map((suggestion) => {
                const style = suggestion.active
                  ? { backgroundColor: "#fafafa", cursor: "pointer" }
                  : { backgroundColor: "#ffffff", cursor: "pointer" };
                return (
                  <div {...getSuggestionItemProps(suggestion, { style })}>
                    {suggestion.description}
                  </div>
                );
              })}
            </div>
          </div>
        )}
      </PlacesAutocomplete>
      {/* The rest of your component here */}
    </div>
  );
};

相关问题