Community Migration

Use this path for apps that import @react-native-community/geolocation, navigator.geolocation, or react-native-nitro-geolocation/compat.

The safest migration is two-step: switch community imports to /compat first and verify the app still behaves the same. Then refactor selected call sites where direct functions or hooks improve ownership, permission timing, cache behavior, or Android settings handling.

Agent Skill

This repository ships an Agent Skills-compatible migration playbook for this path:

npx skills add jingjing2222/react-native-nitro-geolocation --skill community-migration

The skill source is skills/community-migration.

The bundled bootstrap script performs the first safe mechanical pass:

node <skill-dir>/scripts/migrate-to-compat.mjs --root <app-root>

After the compat bootstrap, use the skill to refactor selected call sites.

Migration Path

Step 1: Community Package

import Geolocation from '@react-native-community/geolocation';

Geolocation.getCurrentPosition(
  (position) => {
    console.log(position.coords.latitude, position.coords.longitude);
  },
  (error) => {
    console.error(error.message);
  },
  {
    enableHighAccuracy: true,
    timeout: 15000,
    maximumAge: 0
  }
);

Step 2: Compatibility /compat

First install the Nitro packages:

yarn add react-native-nitro-modules react-native-nitro-geolocation@rc

Then change only the import path:

- import Geolocation from '@react-native-community/geolocation';
+ import Geolocation from 'react-native-nitro-geolocation/compat';

Keep the callback call site unchanged while you verify the app:

Geolocation.getCurrentPosition(
  (position) => {
    console.log(position.coords.latitude, position.coords.longitude);
  },
  (error) => {
    console.error(error.message);
  },
  {
    enableHighAccuracy: true,
    timeout: 15000,
    maximumAge: 0
  }
);

Step 3: Direct functions and hooks

After the /compat migration is stable, replace individual callback call sites with direct functions or hooks:

import {
  getCurrentPosition,
  requestLocationSettings,
  requestPermission,
  setConfiguration
} from 'react-native-nitro-geolocation';

setConfiguration({
  authorizationLevel: 'whenInUse',
  locationProvider: 'playServices'
});

const status = await requestPermission();

if (status === 'granted') {
  await requestLocationSettings({
    accuracy: { android: 'high' },
    interval: 5000,
    fastestInterval: 1000
  });

  const position = await getCurrentPosition({
    accuracy: { android: 'high', ios: 'best' },
    granularity: 'permission',
    waitForAccurateLocation: true,
    timeout: 15000,
    maximumAge: 0
  });

  console.log(position.coords.latitude, position.coords.longitude);
}

For React component watches, prefer useWatchPosition so subscription cleanup is owned by the component lifecycle:

import { useWatchPosition } from 'react-native-nitro-geolocation';

function LocationTracker() {
  const { position, error, isWatching } = useWatchPosition({
    enabled: true,
    accuracy: { android: 'balanced', ios: 'nearestTenMeters' },
    distanceFilter: 10
  });

  if (error) return <Text>{error.message}</Text>;
  if (!position) return <Text>{isWatching ? 'Waiting...' : 'Stopped'}</Text>;

  return (
    <Text>
      {position.coords.latitude}, {position.coords.longitude}
    </Text>
  );
}