react-native-nitro-geolocation 0.1.1 โ†’ 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,10 +10,11 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
10
10
  }
11
11
 
12
12
  private struct LocationRequest {
13
+ let id: UUID = UUID()
13
14
  let success: (GeolocationResponse) -> Void
14
15
  let error: ((GeolocationError) -> Void)?
15
16
  let options: ParsedOptions
16
- var timer: Timer?
17
+ var timer: DispatchSourceTimer?
17
18
  }
18
19
 
19
20
  private struct WatchSubscription {
@@ -22,7 +23,7 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
22
23
  let options: ParsedOptions
23
24
  }
24
25
 
25
- private struct ParsedOptions {
26
+ struct ParsedOptions {
26
27
  let timeout: Double
27
28
  let maximumAge: Double
28
29
  let accuracy: CLLocationAccuracy
@@ -51,7 +52,7 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
51
52
  // MARK: - Properties
52
53
 
53
54
  private var locationManager: CLLocationManager?
54
- private var lastLocation: CLLocation?
55
+ internal private(set) var lastLocation: CLLocation?
55
56
  private var usingSignificantChanges: Bool = false
56
57
 
57
58
  // Authorization
@@ -84,36 +85,32 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
84
85
  success: (() -> Void)?,
85
86
  error: ((GeolocationError) -> Void)?
86
87
  ) {
87
- DispatchQueue.main.async { [weak self] in
88
- guard let self = self else { return }
89
-
90
- self.initializeLocationManagerIfNeeded()
91
- self.enqueueAuthorizationCallbacks(success: success, error: error)
92
-
93
- // Skip permission requests if configured
94
- if skipPermissionRequests {
95
- if enableBackgroundLocationUpdates {
96
- self.enableBackgroundLocationUpdatesIfNeeded()
97
- }
98
- self.handleAuthorizationSuccess()
99
- return
100
- }
88
+ initializeLocationManagerIfNeeded()
89
+ enqueueAuthorizationCallbacks(success: success, error: error)
101
90
 
102
- // Check if already authorized
103
- let currentStatus = CLLocationManager.authorizationStatus()
104
- if currentStatus == .authorizedAlways || currentStatus == .authorizedWhenInUse {
105
- self.handleAuthorizationSuccess()
106
- return
91
+ // Skip permission requests if configured
92
+ if skipPermissionRequests {
93
+ if enableBackgroundLocationUpdates {
94
+ enableBackgroundLocationUpdatesIfNeeded()
107
95
  }
96
+ handleAuthorizationSuccess()
97
+ return
98
+ }
108
99
 
109
- if currentStatus == .denied || currentStatus == .restricted {
110
- self.handleAuthorizationError(for: currentStatus)
111
- return
112
- }
100
+ // Check if already authorized
101
+ let currentStatus = CLLocationManager.authorizationStatus()
102
+ if currentStatus == .authorizedAlways || currentStatus == .authorizedWhenInUse {
103
+ handleAuthorizationSuccess()
104
+ return
105
+ }
113
106
 
114
- // Not determined yet, request permission
115
- self.requestPermission(for: authType)
107
+ if currentStatus == .denied || currentStatus == .restricted {
108
+ handleAuthorizationError(for: currentStatus)
109
+ return
116
110
  }
111
+
112
+ // Not determined yet, request permission
113
+ requestPermission(for: authType)
117
114
  }
118
115
 
119
116
  private func enqueueAuthorizationCallbacks(
@@ -153,63 +150,51 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
153
150
  error: ((GeolocationError) -> Void)?,
154
151
  options: GeolocationOptions?
155
152
  ) {
156
- DispatchQueue.main.async { [weak self] in
157
- guard let self = self else { return }
158
-
159
- let parsedOptions = ParsedOptions.parse(from: options)
160
-
161
- // Check authorization
162
- let status = CLLocationManager.authorizationStatus()
163
- if status == .denied || status == .restricted {
164
- let message =
165
- status == .restricted
166
- ? "This application is not authorized to use location services"
167
- : "User denied access to location services."
168
- error?(self.createError(code: self.PERMISSION_DENIED, message: message))
169
- return
170
- }
171
-
172
- if !CLLocationManager.locationServicesEnabled() {
173
- error?(
174
- self.createError(
175
- code: self.POSITION_UNAVAILABLE, message: "Location services disabled."))
176
- return
177
- }
153
+ let parsedOptions = ParsedOptions.parse(from: options)
154
+
155
+ // Check authorization
156
+ let status = CLLocationManager.authorizationStatus()
157
+ if status == .denied || status == .restricted {
158
+ let message =
159
+ status == .restricted
160
+ ? "This application is not authorized to use location services"
161
+ : "User denied access to location services."
162
+ error?(createError(code: PERMISSION_DENIED, message: message))
163
+ return
164
+ }
178
165
 
179
- // Check cached location
180
- if let cached = self.lastLocation,
181
- self.isCachedLocationValid(cached, options: parsedOptions)
182
- {
183
- success(self.locationToPosition(cached))
184
- return
185
- }
166
+ if !CLLocationManager.locationServicesEnabled() {
167
+ error?(createError(code: POSITION_UNAVAILABLE, message: "Location services disabled."))
168
+ return
169
+ }
186
170
 
187
- self.initializeLocationManagerIfNeeded()
171
+ initializeLocationManagerIfNeeded()
188
172
 
189
- // Configure location manager (use best accuracy from all pending requests)
190
- self.updateLocationManagerConfiguration()
173
+ // Configure location manager
174
+ locationManager?.desiredAccuracy = parsedOptions.accuracy
175
+ locationManager?.distanceFilter = parsedOptions.distanceFilter
191
176
 
192
- // Create request
193
- var request = LocationRequest(
194
- success: success,
195
- error: error,
196
- options: parsedOptions,
197
- timer: nil
198
- )
177
+ // Create request
178
+ var request = LocationRequest(
179
+ success: success,
180
+ error: error,
181
+ options: parsedOptions,
182
+ timer: nil
183
+ )
199
184
 
200
- // Setup timeout
201
- let timer = Timer.scheduledTimer(
202
- withTimeInterval: parsedOptions.timeout / 1000.0, repeats: false
203
- ) { [weak self] timer in
204
- self?.handleTimeout(for: timer)
205
- }
206
- request.timer = timer
185
+ // Setup timeout with DispatchSourceTimer (no run loop needed)
186
+ let timer = DispatchSource.makeTimerSource(queue: .main)
187
+ timer.schedule(deadline: .now() + parsedOptions.timeout / 1000.0)
188
+ timer.setEventHandler { [weak self] in
189
+ self?.handleTimeout(for: request.id)
190
+ }
191
+ timer.resume()
192
+ request.timer = timer
207
193
 
208
- self.pendingRequests.append(request)
194
+ pendingRequests.append(request)
209
195
 
210
- // Start location updates
211
- self.startMonitoring()
212
- }
196
+ // Start location updates
197
+ startMonitoring()
213
198
  }
214
199
 
215
200
  // MARK: - Watch Position
@@ -219,56 +204,44 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
219
204
  error: ((GeolocationError) -> Void)?,
220
205
  options: GeolocationOptions?
221
206
  ) -> Double {
222
- var resultWatchId: Double = 0
223
-
224
- DispatchQueue.main.sync { [weak self] in
225
- guard let self = self else { return }
226
-
227
- let parsedOptions = ParsedOptions.parse(from: options)
228
- let watchId = self.nextWatchId
229
- self.nextWatchId += 1
207
+ let parsedOptions = ParsedOptions.parse(from: options)
208
+ let watchId = nextWatchId
209
+ nextWatchId += 1
210
+
211
+ let subscription = WatchSubscription(
212
+ success: success,
213
+ error: error,
214
+ options: parsedOptions
215
+ )
230
216
 
231
- let subscription = WatchSubscription(
232
- success: success,
233
- error: error,
234
- options: parsedOptions
235
- )
217
+ activeWatches[watchId] = subscription
236
218
 
237
- self.activeWatches[watchId] = subscription
219
+ initializeLocationManagerIfNeeded()
238
220
 
239
- self.initializeLocationManagerIfNeeded()
240
- self.updateLocationManagerConfiguration()
241
- self.startMonitoring()
221
+ // Configure location manager
222
+ locationManager?.desiredAccuracy = parsedOptions.accuracy
223
+ locationManager?.distanceFilter = parsedOptions.distanceFilter
242
224
 
243
- resultWatchId = watchId
244
- }
225
+ startMonitoring()
245
226
 
246
- return resultWatchId
227
+ return watchId
247
228
  }
248
229
 
249
230
  func clearWatch(watchId: Double) {
250
- DispatchQueue.main.async { [weak self] in
251
- guard let self = self else { return }
252
-
253
- self.activeWatches.removeValue(forKey: watchId)
231
+ activeWatches.removeValue(forKey: watchId)
254
232
 
255
- // Stop monitoring if no more watches or pending requests
256
- if self.activeWatches.isEmpty && self.pendingRequests.isEmpty {
257
- self.stopMonitoring()
258
- }
233
+ // Stop monitoring if no more watches or pending requests
234
+ if activeWatches.isEmpty && pendingRequests.isEmpty {
235
+ stopMonitoring()
259
236
  }
260
237
  }
261
238
 
262
239
  func stopObserving() {
263
- DispatchQueue.main.async { [weak self] in
264
- guard let self = self else { return }
240
+ activeWatches.removeAll()
265
241
 
266
- self.activeWatches.removeAll()
267
-
268
- // Stop monitoring if no pending requests
269
- if self.pendingRequests.isEmpty {
270
- self.stopMonitoring()
271
- }
242
+ // Stop monitoring if no pending requests
243
+ if pendingRequests.isEmpty {
244
+ stopMonitoring()
272
245
  }
273
246
  }
274
247
 
@@ -298,7 +271,7 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
298
271
 
299
272
  // 1. Fire all pending getCurrentPosition requests
300
273
  for request in pendingRequests {
301
- request.timer?.invalidate()
274
+ request.timer?.cancel()
302
275
  request.success(position)
303
276
  }
304
277
  pendingRequests.removeAll()
@@ -338,7 +311,7 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
338
311
 
339
312
  // Fire all pending requests with error
340
313
  for request in pendingRequests {
341
- request.timer?.invalidate()
314
+ request.timer?.cancel()
342
315
  request.error?(geoError)
343
316
  }
344
317
  pendingRequests.removeAll()
@@ -355,8 +328,17 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
355
328
 
356
329
  private func initializeLocationManagerIfNeeded() {
357
330
  guard locationManager == nil else { return }
358
- locationManager = CLLocationManager()
359
- locationManager?.delegate = self
331
+
332
+ // CLLocationManager must be created on main thread for delegate callbacks
333
+ if Thread.isMainThread {
334
+ locationManager = CLLocationManager()
335
+ locationManager?.delegate = self
336
+ } else {
337
+ DispatchQueue.main.sync {
338
+ locationManager = CLLocationManager()
339
+ locationManager?.delegate = self
340
+ }
341
+ }
360
342
  }
361
343
 
362
344
  private func updateLocationManagerConfiguration() {
@@ -408,7 +390,7 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
408
390
  }
409
391
  }
410
392
 
411
- private func isCachedLocationValid(_ location: CLLocation, options: ParsedOptions) -> Bool {
393
+ func isCachedLocationValid(_ location: CLLocation, options: ParsedOptions) -> Bool {
412
394
  // Check if maximumAge is infinity
413
395
  if options.maximumAge.isInfinite {
414
396
  return true
@@ -428,13 +410,16 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
428
410
  return true
429
411
  }
430
412
 
431
- private func handleTimeout(for timer: Timer) {
432
- // Find and remove the request with this timer
433
- if let index = pendingRequests.firstIndex(where: { $0.timer === timer }) {
413
+ private func handleTimeout(for requestId: UUID) {
414
+ // Find and remove the request with this ID
415
+ if let index = pendingRequests.firstIndex(where: { $0.id == requestId }) {
434
416
  let request = pendingRequests[index]
435
417
  pendingRequests.remove(at: index)
436
418
 
437
- // Always return timeout error
419
+ // Cancel timer
420
+ request.timer?.cancel()
421
+
422
+ // Return timeout error
438
423
  let timeoutSeconds = request.options.timeout / 1000.0
439
424
  let message = String(format: "Unable to fetch location within %.1fs.", timeoutSeconds)
440
425
  request.error?(createError(code: TIMEOUT, message: message))
@@ -493,7 +478,7 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
493
478
  queuedAuthorizationCallbacks.removeAll()
494
479
  }
495
480
 
496
- private func locationToPosition(_ location: CLLocation) -> GeolocationResponse {
481
+ func locationToPosition(_ location: CLLocation) -> GeolocationResponse {
497
482
  let altitude = location.verticalAccuracy < 0 ? 0.0 : location.altitude
498
483
  let altitudeAccuracy = location.verticalAccuracy < 0 ? 0.0 : location.verticalAccuracy
499
484
  let heading = location.course >= 0 ? location.course : -1.0
@@ -38,6 +38,16 @@ class NitroGeolocation: HybridNitroGeolocationSpec {
38
38
  success: @escaping (GeolocationResponse) -> Void, error: ((GeolocationError) -> Void)?,
39
39
  options: GeolocationOptions?
40
40
  ) throws {
41
+ // Fast path: check cached location immediately (no dispatch overhead!)
42
+ let parsedOptions = LocationManager.ParsedOptions.parse(from: options)
43
+
44
+ if let cached = locationManager.lastLocation,
45
+ locationManager.isCachedLocationValid(cached, options: parsedOptions) {
46
+ success(locationManager.locationToPosition(cached))
47
+ return
48
+ }
49
+
50
+ // Slow path: need GPS
41
51
  locationManager.getCurrentPosition(success: success, error: error, options: options)
42
52
  }
43
53
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-nitro-geolocation",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "โšก๐Ÿš€Blazing-fast geolocation for React Native powered by Nitro Modules",
5
5
  "main": "src/index",
6
6
  "source": "src/index",
@@ -43,7 +43,7 @@
43
43
  "@types/react-test-renderer": "^18.0.0",
44
44
  "react": "19.1.0",
45
45
  "react-native": "0.81.1",
46
- "react-native-nitro-modules": "^0.29.7",
46
+ "react-native-nitro-modules": "^0.29.6",
47
47
  "typescript": "^5.9.3"
48
48
  },
49
49
  "peerDependencies": {
package/README.md DELETED
@@ -1,318 +0,0 @@
1
- # react-native-nitro-geolocation
2
-
3
- [![NPM](https://img.shields.io/npm/v/react-native-nitro-geolocation)](https://www.npmjs.com/package/react-native-nitro-geolocation)
4
-
5
- [`@react-native-community/geolocation`](https://github.com/michalchudziak/react-native-geolocation)
6
- for the **React Native New Architecture** โ€” with 100% API compatibility.
7
-
8
- ![react-native-nitro-geolocation)(https://raw.githubusercontent.com/jingjing2222/react-native-nitro-geolocation/main/demo.gif)
9
-
10
- ---
11
-
12
- ## ๐Ÿ“˜ Documentation
13
-
14
- Full documentation available at:
15
- ๐Ÿ‘‰ [https://react-native-nitro-geolocation.pages.dev](https://react-native-nitro-geolocation.pages.dev)
16
-
17
- ---
18
-
19
- ## ๐Ÿงญ Introduction
20
-
21
- The `@react-native-community/geolocation` package has long been the standard way to access device location in React Native apps.
22
-
23
- With React Native moving toward **Nitro Modules**, **Fabric**, and **JSI**,
24
- this project โ€” **React Native Nitro Geolocation** โ€” brings the same familiar API to the new architecture.
25
-
26
- It provides the **same API surface** with:
27
-
28
- - ๐Ÿš€ Faster performance via direct **JSI bindings**
29
- - ๐Ÿ“ฑ Improved native consistency (Android + iOS)
30
- - ๐Ÿ” Seamless migration from `@react-native-community/geolocation`
31
- - ๐Ÿงฉ TypeScript-first developer experience
32
- - ๐Ÿ”„ 100% API compatibility (drop-in replacement)
33
-
34
- Whether upgrading an existing app or building a new one,
35
- **React Native Nitro Geolocation** keeps the simplicity you know โ€” with modern internals.
36
-
37
- ## ๐Ÿ— Architecture Comparison
38
-
39
- ### ๐Ÿงฉ Origin: Event-based Architecture (`@react-native-community/geolocation`)
40
-
41
- ~~~
42
- JavaScript
43
- โ†“ EventEmitter.addListener('geolocationDidChange', callback)
44
- โ†“ (Callback stored in JS)
45
- React Native Bridge (JSON serialization)
46
- โ†“
47
- Native Layer (Android/iOS)
48
- โ†“ LocationListener receives updates
49
- โ†“ emit('geolocationDidChange', data)
50
- โ†“
51
- EventEmitter dispatches to all listeners
52
- โ†“
53
- User callback executed
54
- ~~~
55
-
56
- **Key traits:**
57
- - Callbacks stored only in JS
58
- - Bridge serialization on every update
59
- - One shared event stream
60
-
61
- ---
62
-
63
- ### โšก Modern: Direct Callback Architecture (`react-native-nitro-geolocation`)
64
-
65
- ~~~
66
- JavaScript
67
- โ†“ Geolocation.watchPosition(success, error)
68
- โ†“ (Callbacks passed directly to native via JSI)
69
- JSI Layer (No Bridge!)
70
- โ†“
71
- Native Layer (Kotlin/Swift)
72
- โ†“ callback.success(position) โ†’ JSI direct call
73
- โ†“
74
- User callback executed immediately
75
- ~~~
76
-
77
- **Key traits:**
78
- - Callbacks passed as native JSI references
79
- - No Bridge serialization
80
- - Independent callback per watcher
81
- - Native โ†’ JS communication in real time
82
-
83
- ---
84
-
85
- ## โšก Quick Start
86
-
87
- ### 1. Installation
88
-
89
- ~~~bash
90
- # Install Nitro core and Geolocation module
91
- yarn add react-native-nitro-modules react-native-nitro-geolocation
92
-
93
- # or using npm
94
- npm install react-native-nitro-modules react-native-nitro-geolocation
95
- ~~~
96
-
97
- After installation, rebuild your native app:
98
-
99
- ~~~bash
100
- cd ios && pod install
101
- ~~~
102
-
103
- ---
104
-
105
- ### 2. iOS Setup
106
-
107
- Add the following permissions to your **Info.plist**:
108
-
109
- ~~~xml
110
- <key>NSLocationWhenInUseUsageDescription</key>
111
- <string>This app requires access to your location while itโ€™s in use.</string>
112
- <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
113
- <string>This app requires access to your location at all times.</string>
114
- ~~~
115
-
116
- ---
117
-
118
- ### 3. Android Setup
119
-
120
- Add these permissions to your **AndroidManifest.xml**:
121
-
122
- ~~~xml
123
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
124
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
125
- ~~~
126
-
127
- Optional (for background access):
128
-
129
- ~~~xml
130
- <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
131
- ~~~
132
-
133
- ---
134
-
135
- ### 4. Usage Example
136
-
137
- ~~~tsx
138
- import Geolocation from 'react-native-nitro-geolocation';
139
-
140
- Geolocation.getCurrentPosition(
141
- (position) => {
142
- console.log('Latitude:', position.coords.latitude);
143
- console.log('Longitude:', position.coords.longitude);
144
- },
145
- (error) => {
146
- console.error('Location error:', error);
147
- },
148
- { enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 }
149
- );
150
-
151
- // Subscribe to continuous updates
152
- const watchId = Geolocation.watchPosition(
153
- (position) => {
154
- console.log('Updated position:', position);
155
- },
156
- (error) => console.error(error),
157
- );
158
- ~~~
159
-
160
- ---
161
-
162
- ### Migrating from `@react-native-community/geolocation`
163
-
164
- Nitro Geolocation is **100% API-compatible** with the original package.
165
- You can migrate simply by replacing imports:
166
-
167
- ~~~diff
168
- - import Geolocation from '@react-native-community/geolocation';
169
- + import Geolocation from 'react-native-nitro-geolocation';
170
- ~~~
171
-
172
- **Benefits:**
173
- - Better performance via JSI
174
- - Reduced bridge overhead
175
- - Improved permission consistency
176
- - Built-in TypeScript definitions
177
-
178
- ---
179
-
180
- ## ๐Ÿง  API Methods
181
-
182
- ### Summary
183
- - `setRNConfiguration`
184
- - `requestAuthorization`
185
- - `getCurrentPosition`
186
- - `watchPosition`
187
- - `clearWatch`
188
- - `stopObserving`
189
-
190
- ---
191
-
192
- ### `setRNConfiguration()`
193
-
194
- Sets configuration options used for all location requests.
195
-
196
- ~~~tsx
197
- import Geolocation from 'react-native-nitro-geolocation';
198
-
199
- Geolocation.setRNConfiguration({
200
- skipPermissionRequests: false,
201
- authorizationLevel: 'auto',
202
- enableBackgroundLocationUpdates: true,
203
- locationProvider: 'auto',
204
- });
205
-
206
- // recommended
207
- import { setRNConfiguration } from 'react-native-nitro-geolocation';
208
-
209
- setRNConfiguration({
210
- skipPermissionRequests: false,
211
- authorizationLevel: 'auto',
212
- enableBackgroundLocationUpdates: true,
213
- locationProvider: 'auto',
214
- });
215
- ~~~
216
-
217
- **Options:**
218
- - `skipPermissionRequests` โ€” default `false`
219
- - `authorizationLevel` โ€” `'always' | 'whenInUse' | 'auto'` *(iOS only)*
220
- - `enableBackgroundLocationUpdates` โ€” *(iOS only)*
221
- - `locationProvider` โ€” `'playServices' | 'android' | 'auto'` *(Android only)*
222
-
223
- ---
224
-
225
- ### `requestAuthorization()`
226
-
227
- Requests location permission from the system.
228
-
229
- ~~~tsx
230
- import Geolocation from 'react-native-nitro-geolocation';
231
-
232
- Geolocation.requestAuthorization(
233
- () => console.log('Permission granted'),
234
- (error) => console.error('Permission error:', error),
235
- );
236
-
237
- // recommended
238
- import { requestAuthorization } from 'react-native-nitro-geolocation';
239
-
240
- requestAuthorization(
241
- () => console.log('Permission granted'),
242
- (error) => console.error('Permission error:', error),
243
- );
244
- ~~~
245
-
246
- ---
247
-
248
- ### `getCurrentPosition()`
249
-
250
- Retrieves the current device location once.
251
-
252
- ~~~tsx
253
- import Geolocation from 'react-native-nitro-geolocation';
254
-
255
- Geolocation.getCurrentPosition(
256
- (position) => console.log(position),
257
- (error) => console.error(error),
258
- { enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 },
259
- );
260
-
261
- // recommended
262
- import { getCurrentPosition } from 'react-native-nitro-geolocation';
263
-
264
- getCurrentPosition(
265
- (position) => console.log(position),
266
- (error) => console.error(error),
267
- { enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 },
268
- );
269
- ~~~
270
-
271
- ---
272
-
273
- ### `watchPosition()`
274
-
275
- Watches location changes and calls the success callback each time.
276
-
277
- ~~~tsx
278
- import Geolocation from 'react-native-nitro-geolocation';
279
-
280
- const id = Geolocation.watchPosition(
281
- (position) => console.log('Position:', position),
282
- (error) => console.error(error),
283
- { interval: 5000, distanceFilter: 10 },
284
- );
285
-
286
- // recommended
287
- import { watchPosition } from 'react-native-nitro-geolocation';
288
-
289
- const id = watchPosition(
290
- (position) => console.log('Position:', position),
291
- (error) => console.error(error),
292
- { interval: 5000, distanceFilter: 10 },
293
- );
294
-
295
- ~~~
296
-
297
- ---
298
-
299
- ### `clearWatch()`
300
-
301
- Stops watching location updates for a given watch ID.
302
-
303
- ~~~tsx
304
- import Geolocation from 'react-native-nitro-geolocation';
305
- Geolocation.clearWatch(id);
306
-
307
- // recommended
308
- import { clearWatch } from 'react-native-nitro-geolocation';
309
- clearWatch(id);
310
- ~~~
311
-
312
- ---
313
-
314
- ## ๐Ÿงช Summary
315
-
316
- **React Native Nitro Geolocation** transforms the geolocation API
317
- from a bridge-based, event-driven system into a **JSI-powered direct-callback model** โ€”
318
- delivering native-level performance with **zero API changes** for developers.