React SDK
@netloc8/react — Context provider, useGeo() hook, and GeoGate component for React.
Installation
bun add @netloc8/react@netloc8/react re-exports everything from @netloc8/core, so you don't need to install both.
Quick Start
import { NetLoc8Provider, useGeo } from '@netloc8/react';
function App() {
return (
<NetLoc8Provider apiKey="pk_live_YOUR_KEY">
<MyApp />
</NetLoc8Provider>
);
}
function LocationBanner() {
const { geo, isLoading, error } = useGeo();
if (isLoading) return <p>Detecting location…</p>;
if (error) return <p>Could not detect location</p>;
return (
<p>
Hello from {geo.location?.city}, {geo.location?.country?.name}!
</p>
);
}NetLoc8Provider
Wrap your app (or a subtree) with NetLoc8Provider to enable the useGeo() hook.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Required |
geo | Partial<Geo> | — | Server-resolved geo data (implies proxy mode) |
mode | "proxy" | "direct" | auto | Override auto-detected mode |
apiKey | string | — | Publishable key pk_... (implies direct mode) |
loading | ReactNode | — | Content shown while geo loads (replaces children) |
rum | boolean | true | Enable performance monitoring |
useGeo()
React hook that returns the current geolocation state. Must be used inside a NetLoc8Provider.
const { geo, isLoading, error } = useGeo();Return Value
| Field | Type | Description |
|---|---|---|
geo | Geo | Current geo data (empty {} while loading) |
isLoading | boolean | true while initial lookup is in progress |
error | Error | null | Non-null if lookup failed |
GeoGate
Declarative component for conditionally rendering content based on geolocation. Supports both allow-list and deny-list patterns.
import { GeoGate } from '@netloc8/react';
{/* EU users — show cookie consent */}
<GeoGate eu={true} loading={<Skeleton />}>
<CookieConsentBanner />
</GeoGate>
{/* Non-EU users */}
<GeoGate eu={false}>
<StandardBanner />
</GeoGate>
{/* Specific countries with fallback */}
<GeoGate country={['US', 'CA']} fallback={<p>Not available in your region</p>}>
<SpecialOffer />
</GeoGate>
{/* Multiple conditions (AND logic) */}
<GeoGate country="US" region="CA" city="San Francisco">
<LocalContent />
</GeoGate>Props
| Prop | Type | Description |
|---|---|---|
children | ReactNode | Content to show when conditions match |
fallback | ReactNode | Content to show when conditions don't match |
loading | ReactNode | Content to show while geo data is loading |
country | string | string[] | Match geo.location?.country?.code |
region | string | string[] | Match geo.location?.region?.code |
city | string | string[] | Match geo.location?.city |
eu | boolean | true = EU countries, false = non-EU |
Preventing Content Shift
The Provider persists geo data in a cookie (__netloc8) so subsequent page loads hydrate instantly without a flash of loading state:
function Header() {
const { geo, isLoading } = useGeo();
// On first visit: isLoading is true briefly
// On subsequent visits: geo is available immediately from cookie
return (
<div>
{!isLoading && geo && (
<span>{geo.location?.country?.flag}</span>
)}
</div>
);
}SSR hydration
For Next.js apps, use @netloc8/nextjs instead. It provides server-side geo fetching so the data is available on first render with no content shift at all.
The Provider collects Core Web Vitals (LCP, INP, CLS, TTFB) by default to help you monitor page performance. Disable with <NetLoc8Provider rum={false}>.