Skip to main content

MapView

Basic Example

A MapView can be declared without any children, with some simple props to set the view and map details. As in a vanilla ArcGIS JS API implementation, the height and width of the map container must be set.

Live Editor
function Example() {
  const OAHU_EXTENT = {
    xmax: -17550549,
    xmin: -17580397,
    ymax: 2461002,
    ymin: 2438185,
    spatialReference: { wkid: 102100 },
  };

  return (
    <MapView
      ViewProperties={{ extent: OAHU_EXTENT }}
      MapProperties={{ basemap: "topo-vector" }}
      style={{ height: "300px", width: "100%" }}
    />
  );
}
Result
Loading...

State-based properties

React state can be used to manage various view and map properties:

Live Editor
function Example() {
  const [ext, setExt] = useState(OAHU_EXTENT);
  const [basemap, setBasemap] = useState("topo-vector");

  return (
    <div className="flex gap-2">
      <div>
        <h5>Change Extent:</h5>
        <div className="flex gap-2 mb-8">
          <button onClick={() => setExt(OAHU_EXTENT)}>Hawaii</button>
          <button onClick={() => setExt(CALIFORNIA_EXTENT)}>California</button>
        </div>

        <h5>Change Basemap:</h5>
        <div className="flex gap-2">
          <button onClick={() => setBasemap("topo-vector")}>Topo Vector</button>
          <button onClick={() => setBasemap("streets")}>Streets</button>
        </div>
      </div>

      <MapView
        ViewProperties={{ extent: ext }}
        MapProperties={{ basemap }}
        style={{ height: "300px", flex: 1 }}
      />
    </div>
  );
}
Result
Loading...

Getting a ref

A ref is available on the MapView which gives you access to the esri map, view, and the MapView DOM element:

Live Editor
function Example() {
  const ref = useRef<MapRef>();

  return (
    <>
      <div className="flex gap-2 mb-2">
        <button onClick={() => console.log(ref.current)}>Log the Ref</button>
        <button
          onClick={() => {
            ref.current.view.goTo(KILAUEA_TARGET, { duration: 5000 });
          }}
        >
          Use the ref to fly to Kilauea Volcano
        </button>
      </div>
      <MapView
        ref={ref}
        ViewProperties={{ extent: HAWAII_EXTENT }}
        MapProperties={{ basemap: "topo-vector" }}
        style={{ height: "300px", width: "100%" }}
      />
    </>
  );
}
Result
Loading...

Externalizing the MapRef with MapContextProvider

It is a very common use case to need to access the underlying map and view instances from outside the MapView container. Instead of using a MapView, you can use a MapViewContext to wrap the parts of your application that need access to the map. When using a MapViewContext, use a MapViewCore, which will read the same context as the rest of your application.

Live Editor
function Menu() {
  const { map, view } = useMap();

  return (
    <nav className="border-blue-800 border p-2">
      <h4>Elsewhere in the component tree</h4>
      <button
        onClick={() => {
          view.goTo(KILAUEA_TARGET, { duration: 5000 });
        }}
      >
        Fly to Kilauea Volcano
      </button>
    </nav>
  );
}

function Example() {
  return (
    <MapContextProvider>
      <div className="flex gap-2">
        <Menu />

        <div className="flex-1 border-green-800 border">
          <MapViewCore
            ViewProperties={{ extent: HAWAII_EXTENT }}
            MapProperties={{ basemap: "topo-vector" }}
            style={{ height: "300px", width: "100%" }}
          />
        </div>
      </div>
    </MapContextProvider>
  );
}

render(<Example />);
Result
Loading...

A MapView creates its own internal MapContextProvider and will ignore any MapContextProviders that you declare, so you must use a MapViewCore to communicate with MapContextProvider.

Events

Numerous events can be listened to with simple event listeners defined on the ViewProperties prop:

Live Editor
function Example() {
  const [point, setPont] = useState();
  const [logs, setLogs] = useState([]);
  const [basemap, setBasemap] = useState("topo-vector");

  return (
    <div>
      <div className="flex justify-between">
        <div>
          <h5>Click the map!</h5>
          <pre>
            {JSON.stringify(
              {
                lat: point?.latitude ?? "waiting for click",
                lon: point?.longitude ?? "waiting for click",
              },
              null,
              2,
            )}
          </pre>
        </div>

        <div>
          <h5>Change Basemap to see layer events:</h5>
          <div className="flex gap-2">
            <button onClick={() => setBasemap("topo-vector")}>
              Topo Vector
            </button>
            <button onClick={() => setBasemap("streets")}>Streets</button>
          </div>
        </div>
      </div>

      <MapView
        style={{ height: "300px", width: "100%" }}
        MapProperties={{ basemap }}
        ViewProperties={{
          extent: OAHU_EXTENT,
          events: {
            click: (e) => {
              setPont(e.mapPoint);
              setLogs([...logs, `click event fired`]);
            },
            "layerview-create": (e) =>
              setLogs([...logs, `layerview-create event fired: ${e.layer.id}`]),
            "layerview-destroy": (e) =>
              setLogs([
                ...logs,
                `layerview-destroy event fired: ${e.layer.id}`,
              ]),
          },
        }}
      />

      <div className="text-amber-50 bg-black w-full p-3">
        <code className="!bg-black">
          {logs.map((l) => (
            <>
              {l}
              <br />
            </>
          ))}
        </code>
      </div>
    </div>
  );
}
Result
Loading...

For a full list of events, see ViewProperties.events.

Events with view access

You can also define the events property as a function of the view, which gives you access to the view object within the callback:

Live Editor
function Example() {
  return (
    <>
      <h4>Click the map to center the view on your click</h4>
      <MapView
        style={{ height: "300px", width: "100%" }}
        MapProperties={{ basemap: "topo-vector" }}
        ViewProperties={{
          extent: OAHU_EXTENT,
          // No need for a ref, view available within callback
          events: (view) => ({
            click: (e) =>
              view.goTo({
                center: [e.mapPoint.longitude, e.mapPoint.latitude],
              }),
          }),
        }}
      />
    </>
  );
}
Result
Loading...