Übersicht
In dieser Anleitung erfahren Sie, wie Sie mit @googlemaps/react-wrapper eine Karte und Markierungen zu einer React-Anwendung hinzufügen und in den Anwendungsstatus einbinden.
@googlemaps/react-wrapper installieren
Installieren und verwenden Sie die Bibliothek @googlemaps/react-wrapper, um die Maps JavaScript API dynamisch zu laden, wenn die Komponente gerendert wird.
npm install @googlemaps/react-wrapper
Diese Bibliothek kann mit den folgenden Objekten importiert und verwendet werden.
import { Wrapper, Status } from "@googlemaps/react-wrapper";
Diese Komponente wird im Wesentlichen verwendet, um untergeordnete Komponenten zu umschließen, die von der Maps JavaScript API abhängig sind. Die Wrapper
-Komponente akzeptiert auch ein render
-Attribut für das Rendern ladender Komponenten oder das Verarbeiten von Fehlern beim Laden der Maps JavaScript API.
const render = (status: Status) => {
return <h1>{status}</h1>;
};
<Wrapper apiKey={"YOUR_API_KEY"} render={render}>
<YourComponent/>
</Wrapper>
Kartenkomponente hinzufügen
Eine einfache Funktionskomponente zum Rendern einer Karte nutzt wahrscheinlich die React-Hooks useRef
, useState
und useEffect
.
Die anfängliche Kartenkomponente hat die folgende Signatur.
const Map: React.FC<{}> = () => {};
Da für google.maps.Map
ein Element
als Konstruktorparameter benötigt wird, ist useRef erforderlich, um ein änderbares Objekt beizubehalten, das für die Lebensdauer der Komponente bestehen bleibt. Mit dem folgenden Snippet wird eine Karte innerhalb des Hooks useEffect im Text der Map
-Komponente instanziiert.
TypeScript
const ref = React.useRef<HTMLDivElement>(null); const [map, setMap] = React.useState<google.maps.Map>(); React.useEffect(() => { if (ref.current && !map) { setMap(new window.google.maps.Map(ref.current, {})); } }, [ref, map]);
JavaScript
const ref = React.useRef(null); const [map, setMap] = React.useState(); React.useEffect(() => { if (ref.current && !map) { setMap(new window.google.maps.Map(ref.current, {})); } }, [ref, map]);
Der obige useEffect
-Hook wird nur ausgeführt, wenn sich ref
geändert hat. Die Map
-Komponente gibt jetzt Folgendes zurück:
return <div ref={ref} />
Kartenkomponente mit zusätzlichen Attributen erweitern
Die grundlegende Kartenkomponente lässt sich mit zusätzlichen Attributen für Kartenoptionen, Event-Listener und Stile erweitern, die auf das „div“-Element mit der Karte angewendet werden. Mit dem folgenden Code wird die erweiterte Oberfläche dieser funktionalen Komponente präsentiert.
interface MapProps extends google.maps.MapOptions {
style: { [key: string]: string };
onClick?: (e: google.maps.MapMouseEvent) => void;
onIdle?: (map: google.maps.Map) => void;
}
const Map: React.FC<MapProps> = ({
onClick,
onIdle,
children,
style,
...options
}) => {}
Das style
-Objekt kann direkt übergeben und als Attribut für das gerenderte div
-Objekt festgelegt werden.
return <div ref={ref} style={style} />;
Für onClick
, onIdle
und google.maps.MapOptions
sind useEffect
-Hooks erforderlich, um das Anwenden von Updates auf google.maps.Map
zu erzwingen.
TypeScript
// because React does not do deep comparisons, a custom hook is used // see discussion in https://github.com/googlemaps/js-samples/issues/946 useDeepCompareEffectForMaps(() => { if (map) { map.setOptions(options); } }, [map, options]);
JavaScript
// because React does not do deep comparisons, a custom hook is used // see discussion in https://github.com/googlemaps/js-samples/issues/946 useDeepCompareEffectForMaps(() => { if (map) { map.setOptions(options); } }, [map, options]);
Für die Event-Listener ist etwas komplexerer Code erforderlich, wenn vorhandene Listener gelöscht werden sollen, sobald ein als Attribut übergebener Handler aktualisiert wurde.
TypeScript
React.useEffect(() => { if (map) { ["click", "idle"].forEach((eventName) => google.maps.event.clearListeners(map, eventName) ); if (onClick) { map.addListener("click", onClick); } if (onIdle) { map.addListener("idle", () => onIdle(map)); } } }, [map, onClick, onIdle]);
JavaScript
React.useEffect(() => { if (map) { ["click", "idle"].forEach((eventName) => google.maps.event.clearListeners(map, eventName) ); if (onClick) { map.addListener("click", onClick); } if (onIdle) { map.addListener("idle", () => onIdle(map)); } } }, [map, onClick, onIdle]);
Markierungskomponente erstellen
Die Markierungskomponente verwendet ähnliche Muster wie die Kartenkomponente mit den Hooks useEffect
und useState
.
TypeScript
const Marker: React.FC<google.maps.MarkerOptions> = (options) => { const [marker, setMarker] = React.useState<google.maps.Marker>(); React.useEffect(() => { if (!marker) { setMarker(new google.maps.Marker()); } // remove marker from map on unmount return () => { if (marker) { marker.setMap(null); } }; }, [marker]); React.useEffect(() => { if (marker) { marker.setOptions(options); } }, [marker, options]); return null; };
JavaScript
const Marker = (options) => { const [marker, setMarker] = React.useState(); React.useEffect(() => { if (!marker) { setMarker(new google.maps.Marker()); } // remove marker from map on unmount return () => { if (marker) { marker.setMap(null); } }; }, [marker]); React.useEffect(() => { if (marker) { marker.setOptions(options); } }, [marker, options]); return null; };
Die Komponente gibt null zurück, da die DOM-Änderungen von google.maps.Map
verwaltet werden.
Markierungen als untergeordnete Komponente der Karte hinzufügen
Zum Hinzufügen der Markierungen zu einer Karte wird die Marker
-Komponente mithilfe des speziellen children
-Attributs wie unten gezeigt an die Map
-Komponente übergeben.
<Wrapper apiKey={"YOUR_API_KEY"}>
<Map center={center} zoom={zoom}>
<Marker position={position} />
</Map>
</Wrapper>
Eine kleine Änderung an der Ausgabe der Map
-Komponente ist erforderlich, damit das Objekt google.maps.Map
als zusätzliches Attribut an alle untergeordneten Elemente übergeben werden kann.
TypeScript
return ( <> <div ref={ref} style={style} /> {React.Children.map(children, (child) => { if (React.isValidElement(child)) { // set the map prop on the child component // @ts-ignore return React.cloneElement(child, { map }); } })} </> );
JavaScript
return ( <> <div ref={ref} style={style} /> {React.Children.map(children, (child) => { if (React.isValidElement(child)) { // set the map prop on the child component // @ts-ignore return React.cloneElement(child, { map }); } })} </> );
Karten- und Anwendungsstatus verknüpfen
Wenn das Muster oben für onClick
- und onIdle
-Callbacks verwendet wird, kann die Anwendung so erweitert werden, dass Nutzeraktionen wie das Klicken oder Schwenken der Karte vollständig eingebunden sind.
TypeScript
const [clicks, setClicks] = React.useState<google.maps.LatLng[]>([]); const [zoom, setZoom] = React.useState(3); // initial zoom const [center, setCenter] = React.useState<google.maps.LatLngLiteral>({ lat: 0, lng: 0, }); const onClick = (e: google.maps.MapMouseEvent) => { // avoid directly mutating state setClicks([...clicks, e.latLng!]); }; const onIdle = (m: google.maps.Map) => { console.log("onIdle"); setZoom(m.getZoom()!); setCenter(m.getCenter()!.toJSON()); };
JavaScript
const [clicks, setClicks] = React.useState([]); const [zoom, setZoom] = React.useState(3); // initial zoom const [center, setCenter] = React.useState({ lat: 0, lng: 0, }); const onClick = (e) => { // avoid directly mutating state setClicks([...clicks, e.latLng]); }; const onIdle = (m) => { console.log("onIdle"); setZoom(m.getZoom()); setCenter(m.getCenter().toJSON()); };
Diese Hooks können mit den folgenden Mustern in die Formularelemente eingebunden werden (wie anhand der Breitengradeingabe gezeigt).
<label htmlFor="lat">Latitude</label>
<input
type="number"
id="lat"
name="lat"
value={center.lat}
onChange={(event) =>
setCenter({ ...center, lat: Number(event.target.value) })
}
/>
Die Anwendung kann schließlich Klicks erfassen und Markierungen an jeder Klickposition rendern.
{clicks.map((latLng, i) => (<Marker key={i} position={latLng} />))}
Code ansehen
Wenn Sie sich den kompletten Beispielcode ansehen möchten, können Sie einen der folgenden Code-Playgrounds nutzen oder das Git-Repository klonen.
Testbeispiel
Klonbeispiel
Git und Node.js sind erforderlich, um dieses Beispiel lokal auszuführen. Folgen Sie dieser Anleitung, um Node.js und NPM zu installieren. Mit den folgenden Befehlen werden der Klonvorgang durchgeführt, Abhängigkeiten installiert und die Beispielanwendung gestartet.
git clone -b sample-react-map https://github.com/googlemaps/js-samples.git
cd js-samples
npm i
npm start
Sie können andere Beispiele ausprobieren, indem Sie zu einem beliebigen Zweig wechseln, der mit sample-SAMPLE_NAME
beginnt.
git checkout sample-SAMPLE_NAME
npm i
npm start