{"id":13505629,"url":"https://github.com/tomwayson/esri-loader-hooks","last_synced_at":"2025-04-19T04:15:22.295Z","repository":{"id":46324638,"uuid":"245555844","full_name":"tomwayson/esri-loader-hooks","owner":"tomwayson","description":"Custom React hooks for using the ArcGIS API for JavaScript with esri-loader.","archived":false,"fork":false,"pushed_at":"2021-08-26T14:57:26.000Z","size":435,"stargazers_count":28,"open_issues_count":14,"forks_count":14,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-29T06:51:15.558Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://esri-loader-hooks.netlify.com/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tomwayson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-03-07T02:41:51.000Z","updated_at":"2024-06-20T02:59:20.000Z","dependencies_parsed_at":"2022-09-05T13:30:54.219Z","dependency_job_id":null,"html_url":"https://github.com/tomwayson/esri-loader-hooks","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomwayson%2Fesri-loader-hooks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomwayson%2Fesri-loader-hooks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomwayson%2Fesri-loader-hooks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomwayson%2Fesri-loader-hooks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tomwayson","download_url":"https://codeload.github.com/tomwayson/esri-loader-hooks/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249191301,"owners_count":21227539,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T00:01:10.864Z","updated_at":"2025-04-19T04:15:22.277Z","avatar_url":"https://github.com/tomwayson.png","language":"JavaScript","funding_links":[],"categories":["Helpers"],"sub_categories":[],"readme":"# esri-loader-hooks\n\nCustom React [hooks](https://reactjs.org/docs/hooks-intro.html) for using the [ArcGIS API for JavaScript](https://developers.arcgis.com/javascript/) with [esri-loader].\n\n## Install\n\n`npm install --save esri-loader esri-loader-hooks` or `yarn add esri-loader esri-loader-hooks`\n\n## Usage\n\n```jsx\nimport {\n  useMap, useScene, useWebMap, useWebScene, // create a map or scene\n  useEvent, useEvents, useWatch, useWatches, // handle events or property changes\n  useGraphic, useGraphics // add graphics to a map/scene\n} from 'esri-loader-hooks';\n```\n\nThis library provides a handful of hooks for [loading ArcGIS maps and scenes](#maps-scenes-and-views) in you components, and then registering [event or watch handles](#events-and-watches), or adding [graphics](#graphics).\n\n### Configure esri-loader\n\nBefore using these hooks you'll need to at least [load the ArcGIS API styles](https://github.com/Esri/esri-loader#loading-styles) and optionally [configure esri-loader](https://github.com/Esri/esri-loader#configuring-esri-loader).\n\n### Maps, Scenes, and Views\n\nYou'll want to start with one of the hooks for working with [maps](https://developers.arcgis.com/javascript/latest/api-reference/esri-Map.html), scenes, and their associated [views](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-View.html).\n\nAll of these hooks return an array where the first element is a [ref](https://reactjs.org/docs/refs-and-the-dom.html) you use to set the DOM node to be used as the view's [container](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-View.html#container), and the second element is the instance of the view, which you can use with the [handler](#events-and-watches) and [graphics](#graphics) hooks below, or in your own hooks.\n\nSee below for more information on [working with view hooks](#working-with-view-hooks).\n\n#### useWebMap\n\nLoad a [`WebMap`](https://developers.arcgis.com/javascript/latest/api-reference/esri-WebMap.html) in a [`MapView`](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html).\n\n```jsx\nimport React from 'react';\nimport { useWebMap } from 'esri-loader-hooks';\n\nfunction WebMap() {\n  // takes map as a string (item id), or JSON (item data)\n  const [ref] = useWebMap('e691172598f04ea8881cd2a4adaa45ba');\n  return \u003cdiv style={{ height: 400 }} ref={ref} /\u003e;\n}\n```\n\nYou can also override view properties by passing [`options`](#arguments).\n\n#### useWebScene\n\nLoad a [`WebScene`](https://developers.arcgis.com/javascript/latest/api-reference/esri-WebScene.html) in a [`SceneView`](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html).\n\n\n```jsx\nimport React from 'react';\nimport { useWebScene } from 'esri-loader-hooks';\n\nfunction WebScene() {\n  // takes scene as a string (item id), or JSON (item data)\n  const [ref] = useWebScene('3a9976baef9240ab8645ee25c7e9c096');\n  return \u003cdiv style={{ height: 400 }} ref={ref} /\u003e;\n}\n```\n\nYou can also override view properties by passing [`options`](#arguments).\n\n#### useMap\n\nLoad a [`Map`](https://developers.arcgis.com/javascript/latest/api-reference/esri-Map.html) in a [`MapView`](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html) with the given [`options`](#options-argument).\n\n```jsx\nimport React from 'react';\nimport { useMap } from 'esri-loader-hooks';\n\nfunction MapView() {\n  // takes initial map and view properties as POJOs\n  const map = {\n    basemap: \"streets\"\n  };\n  const options = {\n    view: {\n      center: [15, 65],\n      zoom: 4\n    }\n  };\n  const [ref] = useMap(map, options);\n  return \u003cdiv style={{ height: 400 }} ref={ref} /\u003e;\n}\n```\n\n#### useScene\n\nLoad a [`Map`](https://developers.arcgis.com/javascript/latest/api-reference/esri-Map.html) in a [`SceneView`](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html) with the given [`options`](#options-argument).\n\n```jsx\nimport React from 'react';\nimport { useScene } from 'esri-loader-hooks';\n\nfunction SceneView() {\n  // takes initial map and view properties as POJOs\n  const map = {\n    basemap: \"streets\",\n    ground: \"world-elevation\"\n  };\n  const options = {\n    view: {\n      scale: 50000000,\n      center: [-101.17, 21.78]\n    }\n  };\n  const [ref] = useScene(map, options);\n  return \u003cdiv style={{ height: 400 }} ref={ref} /\u003e;\n}\n```\n\n### FeatureTables\n\nYou can use the `useFeatureTable` hook to load a stand-alone table or use it in conjunction with a view containing the layer that the table is configured with to enable table to map or table to scene interaction.\n\nLike the hooks above, this hook returns an array where the first element is a [ref](https://reactjs.org/docs/refs-and-the-dom.html) you use to set the DOM node to be used as the table's [container](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureTable.html#container), and the second element is the instance of the table, which you can use with the [handler](#events-and-watches) hook below, or in your own hooks.\n\n#### useFeatureTable\n\nThe `useFeatureTable` hook takes a `layer` parameter which can be a layer item id, a url to a feature layer or scene layer, or a feature or scene layer instance. The second optional parameter is an `options` object used to set any constructor options on the FeatureTable. See [options](#arguments) for general information about this parameter or [FeatureTable properties](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-FeatureTable.html#properties-summary) for the specific table options you can set.\n\nLoad a stand-alone FeatureTable from a layer's URL without a selector column:\n\n```jsx\nimport React from 'react';\nimport {useFeatureTable} from 'esri-loader-hooks';\n\nfunction FeatureTable() {\n  const layerUrl = 'https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/CollegesUniversities/FeatureServer/0';\n  const tableOptions = {\n    visibleElements: { selectionColumn: false }\n  };\n  const [ref] = useFeatureTable(layerUrl, tableOptions);\n  return \u003cdiv style={{ height: 600 }} ref={ref} /\u003e;\n}\n```\n\n### Events and watches\n\nOnce you've used one of the above hooks to load a view, you can register event handlers or watch for property changes with the hooks below.\n\nAll of these hooks clean up after themselves by removing the event or watch handle when the callback changes or the component will un-mount.\n\n#### useEvent\n\n```jsx\nimport React from 'react';\nimport { useMap, useEvent } from 'esri-loader-hooks';\n\nfunction ClickableMap({ onClick }) {\n  const map = {\n    basemap: \"streets\"\n  };\n  const options = {\n    view: {\n      center: [15, 65],\n      zoom: 4\n    }\n  };\n  const [ref, view] = useMap(map, options);\n  // we use the second element returned above to get the view instance\n  useEvent(view, \"click\", onClick);\n  return \u003cdiv style={{ height: 400 }} ref={ref} /\u003e;\n}\n```\n\n#### useEvents\n\nYou can register the same callback for multiple events with `useEvents(view, arrayOfEventNames, callback)`.\n\n#### useWatch\n\nYou can watch for changes to the view, or any instance of [`Accessor`](https://developers.arcgis.com/javascript/latest/api-reference/esri-core-Accessor.html) with the hooks below.\n\n```jsx\nimport React from 'react';\nimport { useScene, useWatch } from 'esri-loader-hooks';\n\nfunction WatchedScene({ onUpdateChange }) {\n  const map = {\n    basemap: \"streets\",\n    ground: \"world-elevation\"\n  };\n  const options = {\n    view: {\n      scale: 50000000,\n      center: [-101.17, 21.78]\n    }\n  };\n  const [ref, view] = useScene(map, options);\n  // we use the second element returned above to get the view instance\n  useWatch(view, 'updating', onUpdateChange);\n  return \u003cdiv style={{ height: 400 }} ref={ref} /\u003e;\n}\n```\n\n#### useWatches\n\nYou can use the same callback to watch changes to multiple properties with `useWatches(anyAccessor, arrayOfPropertyNames, callback)`.\n\n### Graphics\n\nSometimes you have a component that takes a property like coordinates, or an array of geocoding results, and needs to show them as graphics on the view. The hooks below let you do that.\n\n#### useGraphic\n\n```jsx\nimport React from \"react\";\nimport { useMap, useGraphics } from \"esri-loader-hooks\";\n\n// hooks allow us to create a map component as a function\nfunction PointMap({ latitude, longitude }) {\n  const geometry = {\n    type: \"point\", // autocasts as new Point()\n    latitude,\n    longitude\n  };\n  var symbol = {\n    type: \"simple-marker\", // autocasts as new SimpleMarkerSymbol()\n    color: [226, 119, 40],\n  };\n  const map = {\n    basemap: \"hybrid\"\n  };\n  const options = {\n    view: {\n      center: [longitude, latitude],\n      zoom: 3\n    }\n  };\n  const [ref, view] = useMap(map, options);\n  // takes a view instance and graphic as a POJO\n  // the point will be replaced if the lat/lng props change\n  useGraphic(view, { geometry, symbol });\n  return \u003cdiv style={{ height: 400 }} ref={ref} /\u003e;\n}\n```\n\n#### useGraphics\n\nYou can add multiple graphics at the same time with `useGraphics(view, arrayOfJsonGraphics)`.\n\n### Working with view hooks\n\n#### Arguments\n\nAll of these hooks take an optional `options` hash as the final argument. You can pass initial view properties via `options.view`.\n\nOne optional property you can pass to the `options` hash that is not a view or map constructor option is `portalUrl`. Most users will not need to set this and it defaults to ArcGIS Online ('https://www.arcgis.com'). However, if you have a private portal or are a member of the Early Adopters program you may need to load an item or layer from somewhere other than the default ArcGIS Online portal.\n\n**NOTE**: All of the arguments to these hooks will _only_ be used in the map and view constructors. Even if you pass in component props or state the corresponding instance properties will **not** be updated as your component updates.\n\nIf you need to \"bind\" map and/or view properties to props or state, you can add your own `useEffect()` hook like this:\n\n```jsx\nimport React, { useEffect } from 'react';\nimport { useMap } from 'esri-loader-hooks';\n\nfunction ZoomingMap({ zoom = 4 }) {\n  const map = {\n    basemap: 'streets'\n  };\n  const options = {\n    view: {\n      center: [15, 65],\n      // pass zoom in options to set initial zoom (in constructor)\n      zoom\n    }\n  };\n  const [ref, view] = useMap(map, options);\n  // watch for changes to zoom prop and update view\n  useEffect(() =\u003e {\n    if (!view) {\n      // view hasn't been created yet\n      return;\n    }\n    if (view.zoom !== Math.round(zoom, 0)) {\n      // zoom prop has changed, update view\n      view.zoom = zoom;\n    }\n  }, [zoom, view]);\n  return \u003cdiv style={{ height: 400 }} ref={ref} /\u003e;\n}\n```\n\n#### Clean up\n\nAll of these hooks clean up after themselves by destroying the view instance when the component will un-mount.\n\n## FAQ\n\n#### Do these hooks work with version 3.x of the ArcGIS API?\n\nNo.\n\n#### How does this compare to react-arcgis?\n\nThis library is like a hooks version of [react-arcgis](https://github.com/Esri/react-arcgis), which is a library of a few generic components to get you started using esri-loader. My hypothesis is that a library of generic hooks will be more \u003cem\u003euse\u003c/em\u003eful than generic components. This is because the hooks should be easier to compose into many different custom components.\n\n#### Can I use this with the [@arcgis/webpack-plugin](https://github.com/esri/arcgis-webpack-plugin)?\n\nNo. The view and graphics hooks use [esri-loader].\n\nThat said, you probably don't need a library like this if you're using the webpack plugin. The view and graphics hooks help deal with the complexity introduced by the fact that [`loadModules()` is always asynchronous](https://github.com/Esri/esri-loader/#loading-modules-from-the-arcgis-api-for-javascript).\n\nThe event and watch hooks could be used without esri-loader. For now you can copy and paste them into your application. If we add more hooks there, it may make sense to move those into their own library that could be used in both types of applications.\n\n#### Can I use this in my production app?\n\nI'm not (yet), mainly because I don't have a production React app, but you go ahead.\n\n## Contributing\n\nSee [CONTRIBUTING.md](./CONTRIBUTING.md).\n\n## Development\n\nSee [the development instructions](./CONTRIBUTING.md#development).\n\n[esri-loader]:https://github.com/Esri/esri-loader\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomwayson%2Fesri-loader-hooks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomwayson%2Fesri-loader-hooks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomwayson%2Fesri-loader-hooks/lists"}