GithubHelp home page GithubHelp logo

antonis0490 / esri-loader-hooks Goto Github PK

View Code? Open in Web Editor NEW

This project forked from tomwayson/esri-loader-hooks

0.0 1.0 0.0 277 KB

Custom React hooks for using the ArcGIS API for JavaScript with esri-loader.

Home Page: https://esri-loader-hooks.netlify.com/

License: MIT License

JavaScript 62.29% HTML 1.98% TypeScript 34.43% CSS 1.29%

esri-loader-hooks's Introduction

esri-loader-hooks

Custom React hooks for using the ArcGIS API for JavaScript with esri-loader.

Install

npm install --save esri-loader esri-loader-hooks or yarn add esri-loader esri-loader-hooks

Usage

import { 
  useMap, useScene, useWebMap, useWebScene, // create a map or scene
  useEvent, useEvents, useWatch, useWatches, // handle events or property changes
  useGraphic, useGraphics // add graphics to a map/scene
} from 'esri-loader-hooks';

This library provides a handful of hooks for loading ArcGIS maps and scenes in you components, and then registering event or watch handles, or adding graphics.

Configure esri-loader

Before using these hooks you'll need to at least load the ArcGIS API styles and optionally configure esri-loader.

Maps, Scenes, and Views

You'll want to start with one of the hooks for working with maps, scenes, and their associated views.

All of these hooks return an array where the first element is a ref you use to set the DOM node to be used as the view's container, and the second element is the instance of the view, which you can use with the handler and graphics hooks below, or in your own hooks.

See below for more information on working with view hooks.

useWebMap

Load a WebMap in a MapView.

import React from 'react';
import { useWebMap } from 'esri-loader-hooks';

function WebMap() {
  // takes map as a string (item id), or JSON (item data)
  const [ref] = useWebMap('e691172598f04ea8881cd2a4adaa45ba');
  return <div style={{ height: 400 }} ref={ref} />;
}

You can also override view properties by passing options.

useWebScene

Load a WebScene in a SceneView.

import React from 'react';
import { useWebScene } from 'esri-loader-hooks';

function WebScene() {
  // takes scene as a string (item id), or JSON (item data)
  const [ref] = useWebScene('3a9976baef9240ab8645ee25c7e9c096');
  return <div style={{ height: 400 }} ref={ref} />;
}

You can also override view properties by passing options.

useMap

Load a Map in a MapView with the given options.

import React from 'react';
import { useMap } from 'esri-loader-hooks';

function MapView() {
  // takes initial map and view properties as POJOs
  const map = {
    basemap: "streets"
  };
  const options = {
    view: {
      center: [15, 65],
      zoom: 4
    }
  };
  const [ref] = useMap(map, options);
  return <div style={{ height: 400 }} ref={ref} />;
}

useScene

Load a Map in a SceneView with the given options.

import React from 'react';
import { useScene } from 'esri-loader-hooks';

function SceneView() {
  // takes initial map and view properties as POJOs
  const map = {
    basemap: "streets",
    ground: "world-elevation"
  };
  const options = {
    view: {
      scale: 50000000,
      center: [-101.17, 21.78]
    }
  };
  const [ref] = useScene(map, options);
  return <div style={{ height: 400 }} ref={ref} />;
}

Events and watches

Once 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.

All of these hooks clean up after themselves by removing the event or watch handle when the callback changes or the component will un-mount.

useEvent

import React from 'react';
import { useMap, useEvent } from 'esri-loader-hooks';

function ClickableMap({ onClick }) {
  const map = {
    basemap: "streets"
  };
  const options = {
    view: {
      center: [15, 65],
      zoom: 4
    }
  };
  const [ref, view] = useMap(map, options);
  // we use the second element returned above to get the view instance
  useEvent(view, "click", onClick);
  return <div style={{ height: 400 }} ref={ref} />;
}

useEvents

You can register the same callback for multiple events with useEvents(view, arrayOfEventNames, callback).

useWatch

You can watch for changes to the view, or any instance of Accessor with the hooks below.

import React from 'react';
import { useScene, useWatch } from 'esri-loader-hooks';

function WatchedScene({ onUpdateChange }) {
  const map = {
    basemap: "streets",
    ground: "world-elevation"
  };
  const options = {
    view: {
      scale: 50000000,
      center: [-101.17, 21.78]
    }
  };
  const [ref, view] = useScene(map, options);
  // we use the second element returned above to get the view instance
  useWatch(view, 'updating', onUpdateChange);
  return <div style={{ height: 400 }} ref={ref} />;
}

useWatches

You can use the same callback to watch changes to multiple properties with useWatches(anyAccessor, arrayOfPropertyNames, callback).

Graphics

Sometimes 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.

useGraphic

import React from "react";
import { useMap, useGraphics } from "esri-loader-hooks";

// hooks allow us to create a map component as a function
function PointMap({ latitude, longitude }) {
  const geometry = {
    type: "point", // autocasts as new Point()
    latitude, 
    longitude
  };
  var symbol = {
    type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
    color: [226, 119, 40],
  };
  const map = {
    basemap: "hybrid"
  };
  const options = {
    view: {
      center: [longitude, latitude],
      zoom: 3
    }
  };
  const [ref, view] = useMap(map, options);
  // takes a view instance and graphic as a POJO
  // the point will be replaced if the lat/lng props change
  useGraphic(view, { geometry, symbol });
  return <div style={{ height: 400 }} ref={ref} />;
}

useGraphics

You can add multiple graphics at the same time with useGraphics(view, arrayOfJsonGraphics).

Working with view hooks

Arguments

All of these hooks take an optional options hash as the final argument. You can pass initial view properties via options.view.

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.

If you need to "bind" map and/or view properties to props or state, you can add your own useEffect() hook like this:

import React, { useEffect } from 'react';
import { useMap } from 'esri-loader-hooks';

function ZoomingMap({ zoom = 4 }) {
  const map = {
    basemap: 'streets'
  };
  const options = {
    view: {
      center: [15, 65],
      // pass zoom in options to set initial zoom (in constructor)
      zoom
    }
  };
  const [ref, view] = useMap(map, options);
  // watch for changes to zoom prop and update view
  useEffect(() => {
    if (!view) {
      // view hasn't been created yet
      return;
    }
    if (view.zoom !== Math.round(zoom, 0)) {
      // zoom prop has changed, update view
      view.zoom = zoom;
    }
  }, [zoom, view]);
  return <div style={{ height: 400 }} ref={ref} />;
}

Clean up

All of these hooks clean up after themselves by destroying the view instance when the component will un-mount.

FAQ

Do these hooks work with version 3.x of the ArcGIS API?

No.

How does this compare to react-arcgis?

This library is like a hooks version of 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 useful than generic components. This is because the hooks should be easier to compose into many different custom components.

Can I use this with the @arcgis/webpack-plugin?

No. The view and graphics hooks use esri-loader.

That 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.

The 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.

Can I use this in my production app?

I'm not (yet), mainly because I don't have a production React app, but you go ahead.

Contributing

See CONTRIBUTING.md.

Development

See the development instructions.

esri-loader-hooks's People

Contributors

tomwayson avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.