Typed Arrays and Batch Calls
Cell Sets as Typed Arrays
Section titled “Cell Sets as Typed Arrays”Cell collections use BigUint64Array:
import { gridDisk, latLngToCell } from 'react-native-nitro-h3'
const cell = latLngToCell(37.7749, -122.4194, 9)const cells = gridDisk(cell, 10) // BigUint64Array, 331 cellsA result crosses as one ArrayBuffer and is viewed in place, with no per-element copy and no string conversion.
A set near a pentagon is shorter than its formula predicts, because H3 pads its output with holes there and this package removes them before the buffer crosses.
Read length rather than assuming the 1 + 3k(k + 1) cells a disk holds elsewhere.
The Batch Calls
Section titled “The Batch Calls”Three batch calls process a whole typed array in one native call:
import { latLngsToCells, cellsToLatLngs, cellsToBoundaries,} from 'react-native-nitro-h3'
const coords = new Float64Array([ 37.7749, -122.4194, 37.8044, -122.2712,])
const cells = latLngsToCells(coords, 9) // BigUint64Array, one cell per pairconst centres = cellsToLatLngs(cells) // Float64Array, [lat0, lng0, lat1, lng1, ...]Coordinates use interleaved [latitude, longitude] pairs.
The batch calls are additive and are not part of the h3-js compatibility surface, which Divergences from h3-js records.
parity/divergences.test.ts asserts that h3-js exports none of the three, so the day it grows one this sentence fails rather than ages.
They are intended for workloads where repeatedly crossing the JS/native boundary would otherwise dominate execution time.
The saving is the crossing, not a faster inner loop. Host measurements put the native work of a batch call within about 2 % of the native work of the loop it replaces over 100,000 elements, so what disappears is the per-element crossing. The crossing costs roughly 0.38 and 0.89 microseconds per element on the A12, 0.28 and 1.04 on the Galaxy S23. See Benchmark Report for the conditions.
latLngsToCells
Section titled “latLngsToCells”Reach for this call when a coordinate set already sits in a Float64Array, because one native call replaces one boundary crossing per pair.
coords is interleaved [lat0, lng0, lat1, lng1, ...] in degrees, latitude first, the reverse of the GeoJSON order, and the result holds one cell per pair in input order.
The cell ceiling applies, counted in cells (one cell per pair).
See latLngsToCells for the signature and the full error list.
cellsToLatLngs
Section titled “cellsToLatLngs”Reach for this call when a renderer wants centres rather than cells, because it answers the flat coordinate buffer circle layers and heatmaps consume.
The result is interleaved [lat0, lng0, lat1, lng1, ...] in degrees, latitude first again, two entries per cell.
The cell ceiling applies, counted in cells, and is checked before the first centre is read.
See cellsToLatLngs for the signature and the full error list.
cellsToBoundaries
Section titled “cellsToBoundaries”Reach for this call when a renderer builds meshes or paths, because it reads the boundary of every cell into a fixed-stride buffer that can be walked by index:
const { stride, vertices, vertexCounts } = cellsToBoundaries(cells)for (let i = 0; i < cells.length; i++) { const base = i * stride for (let j = 0; j < vertexCounts[i]; j++) { path.lineTo(project(vertices[base + 2 * j], vertices[base + 2 * j + 1])) }}strideis always20, ten[lat, lng]pairs, which is H3’sMAX_CELL_BNDRY_VERTSdoubled. Cellistarts ati * stride, so any cell is reached without a scan.vertexCounts[i]is how many of those pairs are real, with5for a pentagon at an even resolution and10at an odd one,6for a hexagon,7or8where a hexagon crosses an icosahedron edge.- Slots past the count hold
NaN, never0, so a read past the count is visible instead of landing off the coast of Africa. - Vertices are in the same order and the same degrees
cellToBoundaryanswers, latitude first. - The cell ceiling applies, counted in cells, and is checked before anything is allocated. One cell weighs 161 bytes here, 160 of vertices and 1 of count, rather than the 8 bytes of a cell set.
See cellsToBoundaries for the signature and the full error list.
What a Batch Call Saves
Section titled “What a Batch Call Saves”The saving is the bridge crossings that no longer happen. Same conditions as the headline benchmark (iPhone XS, iOS 18.7.9, React Native 0.87.0, Hermes, 20-run median, 2026-09-01). Full data in Benchmark Report.
Whether a batch call pays for a given input size is covered in Performance Guide, and the measured rows are W11 and W12 in Benchmark Report.
Below a few hundred elements the crossover is unmeasured, so measure the sizes your own app actually passes before you switch a loop to a batch call.