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.
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%" }} /> ); }
State-based properties
React state can be used to manage various view and map properties:
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> ); }
Getting a ref
A ref
is available on the MapView
which gives you access to the esri map
, view
, and the MapView
DOM element
:
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%" }} /> </> ); }
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.
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 />);
A MapView
creates its own internal MapContextProvider
and will ignore any MapContextProvider
s 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:
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> ); }
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:
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], }), }), }} /> </> ); }