Adaptador React¶
geoworld-react en npm: un
provider y hooks sobre el cliente JavaScript. Cero
dependencias en runtime; react (≥ 18) y geoworld son peers. El código
vive en
packages/js/geoworld-react.
Provider y hooks¶
import { createClient } from "geoworld";
import { GeoWorldProvider, useBoundaries, useCountries } from "geoworld-react";
const world = createClient({ version: "1.0.0" });
export function App() {
return (
<GeoWorldProvider client={world}>
<Regions iso3="CHL" />
</GeoWorldProvider>
);
}
function Regions({ iso3 }: { iso3: string }) {
const regions = useBoundaries(iso3, "ADM1");
if (regions.status !== "success") return <p>{regions.status}</p>;
return (
<ul>
{regions.data.features.map((f) => <li key={f.id}>{f.properties.shapeName}</li>)}
</ul>
);
}
| Hook | Recurso |
|---|---|
useIndex() |
todo el index.json |
useCountries() |
un resumen por territorio |
useCountry(iso3) |
la entrada completa del índice (niveles, licencia, términos, datasets) |
useBoundaries(iso3, level, { part?, preview?, enabled? }) |
una FeatureCollection |
useFeature(id) |
una feature por id estable |
useChildren(id) |
las features del siguiente nivel publicado bajo ese id |
useResource(key, loader) |
cualquier otra cosa, a través del mismo store |
Cada hook devuelve un recurso:
{ status: "idle" | "loading" | "success" | "error"; data?: T; error?: unknown; reload(): Promise<void> }
data está tipado como presente solo cuando status === "success", así que
basta un if que estreche el tipo. Pasar null o undefined como iso3,
level o id, o enabled: false, deja el recurso en idle sin desmontar
el componente. reload() vuelve a cargar aunque ya esté cargado; con la
caché en memoria por defecto del cliente, eso solo vuelve a descargar tras
un error.
Qué hace el store¶
El cliente cachea promesas, que React no puede leer durante el render. Por
eso el provider tiene un pequeño store con clave por petición
(["boundaries", "CHL", "ADM1", null, false]): dos componentes que piden el
mismo nivel disparan una sola descarga, un componente que se monta cuando el
dato ya está renderiza success en su primer paso, y reload/invalidate
tienen un sitio donde vivir. useGeoWorld() devuelve { client, store };
createStore() construye uno para cebarlo en el servidor o compartirlo entre
providers:
import { createStore, keys } from "geoworld-react";
const store = createStore();
await store.load(keys.boundaries("CHL", "ADM1"), () => world.get("CHL", "ADM1"));
// <GeoWorldProvider client={world} store={store}> renderiza ese nivel como success de inmediato
Las claves ponen en mayúsculas el territorio y el nivel, así que
useBoundaries("chl", "adm1") y useBoundaries("CHL", "ADM1") comparten
una entrada.
En un mapa¶
Los hooks dan los datos; los adaptadores de mapa los ponen en pantalla. Con
geoworld-maplibre, pasa el cliente del provider a
addBoundaries dentro de un efecto; con geoworld-leaflet,
lo mismo con withLeaflet(L).addBoundaries. El id estable de cada feature
es lo que permite que una lista en React y una capa en el mapa hablen de la
misma unidad.
Ejemplo¶
examples/react.html
ejecuta los hooks con React desde un CDN y sin paso de build: selector de
territorio y nivel, la lista de features y useChildren al hacer clic.
just examples la sirve.