Watch-IP

تحديد الموقع الجغرافي لعنوان IP في React: مكوّن لموقع الزائر

أنشئ خطّاف useVisitorGeo قابلًا لإعادة الاستخدام حول حزمة Watch-IP لجافاسكريبت (SDK)، مع معالجة التحميل والخطأ والإلغاء التي يحتاجها مكوّن React حقيقي — بما في ذلك سبب احتمال إطلاق الطلب مرتين في وضع التطوير.

قبل أن تبدأ

  • حساب Watch-IP ومفتاح زوار قابل للنشر يتضمن نطاق تطبيقك (بيئتي التطوير والإنتاج) في قائمة النطاقات المسموح بها.
  • React 18 أو أحدث — سلوك الاستدعاء المزدوج في StrictMode الموضَّح أدناه خاص بوضع التطوير فقط.
  • تثبيت @digitload/watch-ip-sdk (npm install @digitload/watch-ip-sdk).

1. إنشاء خطّاف useVisitorGeo

غلِّف استدعاء getGeo() الخاص بالحزمة (SDK) داخل خطّاف يتتبع حالة التحميل/النتيجة/الخطأ، ويُلغي الطلب إذا أُزيل المكوّن قبل اكتمال الطلب.

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. لماذا قد يُطلَق الطلب مرتين في وضع التطوير

يقوم StrictMode في React عمدًا بتركيب كل مكوّن وإزالته وإعادة تركيبه مرة واحدة في وضع التطوير لكشف التأثيرات (effects) التي لا تُنظِّف نفسها. وهذا يعني أن تأثير هذا الخطّاف يعمل مرتين، وهنا تكمن أهمية AbortController أعلاه: يُلغى الطلب الأول بواسطة دالة التنظيف قبل اكتماله، بحيث لا يكتمل فعليًا سوى استدعاء واحد حقيقي لـ getGeo(). تخطي استدعاء الإلغاء لن يُخلّ بالصحة — فـ 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؟ يُغيّر نموذج العرض من جانب الخادم فيه المكان الذي يمكن فيه تشغيل هذا الطلب بأمان — راجع دليل Next.js للاطلاع على التقسيم بين العميل والخادم، ونمط خادم بمفتاح سري للعناوين المُقدَّمة يدويًا.

صفحات ذات صلة