Watch-IP

IP-Geolokalisierung in React: Eine Komponente für den Besucherstandort

Erstellen Sie einen wiederverwendbaren useVisitorGeo-Hook rund um das Watch-IP-JavaScript-SDK, mit der Lade-, Fehler- und Abbruchbehandlung, die eine echte React-Komponente benötigt — einschließlich der Erklärung, warum die Anfrage in der Entwicklung zweimal ausgelöst werden kann.

Bevor Sie beginnen

  • Ein Watch-IP-Konto und ein veröffentlichbarer Besucher-Schlüssel, dessen Liste erlaubter Origins den Origin Ihrer Anwendung enthält (Entwicklung und Produktion).
  • React 18 oder neuer — das unten beschriebene doppelte Aufrufverhalten von StrictMode ist spezifisch für den Entwicklungsmodus.
  • @digitload/watch-ip-sdk installiert (npm install @digitload/watch-ip-sdk).

1. Einen useVisitorGeo-Hook erstellen

Umschließen Sie den getGeo()-Aufruf des SDK mit einem Hook, der den Zustand Lade/Ergebnis/Fehler verfolgt und die Anfrage abbricht, wenn die Komponente ausgehängt wird, bevor sie abgeschlossen ist.

TypeScript

import { useEffect, useState } from "react";
import { WatchIP, type GeoResponse } from "@digitload/watch-ip-sdk";

const client = new WatchIP("YOUR_PUBLISHABLE_KEY");

export function useVisitorGeo() {
  const [geo, setGeo] = useState<GeoResponse | null>(null);
  const [status, setStatus] = useState<"loading" | "ready" | "error">("loading");

  useEffect(() => {
    const controller = new AbortController();

    client
      .getGeo({ signal: controller.signal })
      .then((result) => {
        setGeo(result);
        setStatus("ready");
      })
      .catch((err) => {
        if (err.name !== "AbortError") setStatus("error");
      });

    return () => controller.abort();
  }, []);

  return { geo, status };
}

2. Warum die Anfrage in der Entwicklung zweimal ausgelöst werden kann

Reacts StrictMode montiert, hängt aus und montiert jede Komponente in der Entwicklung absichtlich einmal erneut, um Effekte aufzudecken, die sich nicht selbst aufräumen. Das bedeutet, der Effekt dieses Hooks läuft zweimal, und der AbortController oben ist wichtig: Die erste Anfrage wird durch die Cleanup-Funktion abgebrochen, bevor sie abgeschlossen ist, sodass tatsächlich nur ein einziger echter getGeo()-Aufruf abgeschlossen wird. Das Weglassen des abort()-Aufrufs würde die Korrektheit nicht verletzen — GET /v1/geo ist eine Leseoperation —, würde aber eine überflüssige, noch laufende Anfrage und ein Zustands-Update hinterlassen, das die verworfene erste Instanz nie verwendet.

3. Lade-, Ergebnis- und Fallback-Zustände rendern

Verwenden Sie den Hook wie jeden anderen Daten-Hook, wobei ein sinnvoller Standardzustand sichtbar bleibt, solange status nicht 'loading' verlassen hat.

TypeScript (JSX)

function RegionBanner() {
  const { geo, status } = useVisitorGeo();

  if (status === "loading") return <p>Region wird ermittelt…</p>;
  if (status === "error" || !geo?.country) return <p>Standardregion wird angezeigt</p>;
  return <p>Inhalte werden angezeigt für {geo.city ?? geo.country}</p>;
}

4. Eine explizite Entscheidung des Besuchers beibehalten

Dieselbe Regel wie im reinen JavaScript-Leitfaden: Prüfen Sie auf eine gespeicherte Präferenz, bevor Sie das vorgeschlagene Land anwenden, und greifen Sie nur dann auf das Ergebnis des Hooks zurück, wenn noch keine Präferenz existiert.

TypeScript

const preferred = localStorage.getItem("preferredCountry");
const country = preferred ?? geo?.country ?? "US";

Fehler und Grenzfälle

Ein nicht erlaubter Origin schlägt fehl, bevor Ihr Code eine normale Antwort sieht — fügen Sie zuerst die Entwicklungs- und Produktions-URLs der App zu den erlaubten Origins des Schlüssels hinzu. Jedes Feld von GeoResponse außer ip und isEUCountry ist nullable, daher reicht status === 'ready' allein nicht aus; prüfen Sie außerdem das konkrete Feld, das Sie gleich rendern wollen, so wie es der obige Fallback mit geo?.country tut.

Nächster Schritt

Verwenden Sie Next.js? Dessen Server-Rendering-Modell ändert, wo diese Anfrage sicher ausgeführt werden kann — siehe den Next.js-Leitfaden für die Client-/Server-Aufteilung und ein serverseitiges Muster mit geheimem Schlüssel für gelieferte IPs.

Verwandte Seiten