ReactでのIPジオロケーション:訪問者位置情報コンポーネント
Watch-IP JavaScript SDKを使って再利用可能なuseVisitorGeoフックを構築します。実際のReactコンポーネントに必要な読み込み中、エラー、キャンセル処理を含み、開発時にリクエストが2回発生する理由も解説します。
始める前に
- Watch-IPアカウントと、アプリのオリジン(開発環境と本番環境の両方)を許可オリジンリストに含めた公開可能な訪問者用キー。
- React 18以降—以下で説明するStrictModeの二重呼び出しの挙動は開発モードに特有のものです。
- @digitload/watch-ip-sdkがインストール済み(npm install @digitload/watch-ip-sdk)。
1. useVisitorGeoフックを構築する
SDKのgetGeo()呼び出しをフックでラップし、loading/result/errorの状態を追跡するとともに、レスポンスが返る前にコンポーネントがアンマウントされた場合はリクエストをキャンセルします。
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. 開発時にリクエストが2回発生する理由
ReactのStrictModeは、後始末をしないエフェクトを見つけ出すために、開発時に各コンポーネントを意図的に一度マウント・アンマウント・再マウントします。つまりこのフックのエフェクトは2回実行され、上記のAbortControllerが重要になります:最初のリクエストは解決する前にクリーンアップ関数によって中止されるため、実際に完了するgetGeo()呼び出しは1回だけです。中止処理を省略しても正しさが損なわれるわけではありません—GET /v1/geoは読み取りです—が、破棄された最初のインスタンスが決して使わない、冗長な進行中のリクエストと状態更新が残ってしまいます。
3. 読み込み中、結果、フォールバックの各状態を描画する
他のデータフックと同じ要領でこのフックを使い、statusが'loading'から抜けるまでは適切なデフォルト表示を維持します。
TypeScript (JSX)
function RegionBanner() {
const { geo, status } = useVisitorGeo();
if (status === "loading") return <p>地域を検出しています…</p>;
if (status === "error" || !geo?.country) return <p>デフォルトの地域を表示しています</p>;
return <p>{geo.city ?? geo.country}向けのコンテンツを表示しています</p>;
}4. 訪問者の明示的な選択を優先する
プレーンなJavaScriptガイドと同じルールです:提案された国を適用する前に保存済みの設定がないか確認し、まだ設定が存在しない場合にのみフックの結果にフォールバックしてください。
TypeScript
const preferred = localStorage.getItem("preferredCountry");
const country = preferred ?? geo?.country ?? "US";エラーとエッジケース
許可されていないオリジンは、コードが通常のレスポンスを目にする前に失敗します—まずアプリの開発用・本番用URLをキーの許可オリジンに追加してください。GeoResponseのipとisEUCountryを除くすべてのフィールドはnullになりうるため、status === 'ready'だけでは不十分です。上記のフォールバックがgeo?.countryで行っているように、描画しようとしている個別のフィールドも確認してください。
次のステップ
Next.jsを使っていますか?そのサーバーレンダリングモデルは、このリクエストを安全に実行できる場所を変えます—クライアント/サーバーの使い分けと、指定したIPに対するシークレットキーを使ったサーバーパターンについてはNext.jsガイドをご覧ください。