React SDK

@netloc8/react — Context provider, useGeo() hook, and GeoGate component for React.

Installation

Bash
bun add @netloc8/react

@netloc8/react re-exports everything from @netloc8/core, so you don't need to install both.

Quick Start

App.jsx
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

PropTypeDefaultDescription
childrenReactNodeRequired
geoPartial<Geo>Server-resolved geo data (implies proxy mode)
mode"proxy" | "direct"autoOverride auto-detected mode
apiKeystringPublishable key pk_... (implies direct mode)
loadingReactNodeContent shown while geo loads (replaces children)
rumbooleantrueEnable performance monitoring

useGeo()

React hook that returns the current geolocation state. Must be used inside a NetLoc8Provider.

JavaScript
const { geo, isLoading, error } = useGeo();

Return Value

FieldTypeDescription
geoGeoCurrent geo data (empty {} while loading)
isLoadingbooleantrue while initial lookup is in progress
errorError | nullNon-null if lookup failed

GeoGate

Declarative component for conditionally rendering content based on geolocation. Supports both allow-list and deny-list patterns.

JSX
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

PropTypeDescription
childrenReactNodeContent to show when conditions match
fallbackReactNodeContent to show when conditions don't match
loadingReactNodeContent to show while geo data is loading
countrystring | string[]Match geo.location?.country?.code
regionstring | string[]Match geo.location?.region?.code
citystring | string[]Match geo.location?.city
eubooleantrue = 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:

JSX
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}>.