I'm developing a single page application with JavaScript Maps SDK (4.32), React (18), React Redux (8), TypeScript (5), and Webpack (5). I save TimeExtent in the Redux store and would like to use it to change the TimeExtent on the arcgis-map component. Here's my code...
/// <reference types="@arcgis/map-components/types/react" />
import React from "react";
import { useSelector } from "react-redux";
import "@arcgis/map-components/components/arcgis-map";
export function MyMap() {
const mapState = useSelector((state: StoreState) => state.map);
const { webMapItemID, timeExtent } = mapState;
return (
<arcgis-map
item-id={webMapItemID}
timeExtent={timeExtent}>
onarcgisViewReadyChange={(event) => console.log("ready")}
</arcgis-map>
);
}
This code does not work. Specifically, the time extent is never set on the map (the time extent is correct, but the map never sets it internally) and the ready change event is never called (nothing is written to the console).
However, I can set the time extent and listen for the ready change event by obtaining a reference to the arcgis-map web component on mount.
/// <reference types="@arcgis/map-components/types/react" />
import React, { useEffect } from "react";
import { useSelector } from "react-redux";
import "@arcgis/map-components/components/arcgis-map";
export function MyMap() {
const mapState = useSelector((state: StoreState) => state.map);
const { webMapItemID, timeExtent } = mapState;
useEffect(() => {
const map = document.querySelector("arcgis-map");
map?.addEventListener("arcgisViewReadyChange", (event) => {
map.view.timeExtent = timeExtent;
});
}, []);
return <arcgis-map item-id={webMapItemID}></arcgis-map>;
}
What am I not understanding about the first example? What is the recommended programming pattern when using web components, react 18, and redux?
I believe I see the issue. Some of the code completions I see in the IDE are for properties and not attributes. Per this documentation properties can only be set via programmatically via JavaScript. The Map Component page lists which properties have corresponding attributes that can be set in HTML. Time Extent is only a property and must be set via JavaScript.
However, that does not explain why my event doesn't fire. It looks like it should per this example.
If you are using React 18, you need to use the map-components-react wrapper to get proper bindings. React 19+ supports native web components, but not 18.
Thanks. I now have the following code.
export function MyMap() {
const mapRef = useRef<HTMLArcgisMapElement>(null);
const mapState = useSelector((state: StoreState) => state.map);
const { webMapItemID, timeExtent: timeExtent } = mapState;
useEffect(() => {
if (mapRef.current && timeExtent) {
mapRef.current.view.timeExtent = timeExtent;
}
}, [timeExtent]);
return (
<div style={{ width: "100%", height: "100%" }}>
<ArcgisMap
id="my-map"
ref={mapRef}
itemId={webMapItemID}
onArcgisViewReadyChange={() => {
mapRef.current!.view.timeExtent = timeExtent;
}}
></ArcgisMap>
</div>
);
}
The ready event and time extent are working, but with an unexpected side effect. It appears the that entire map is re-rendered. When the time extent changes the map briefly goes white and then comes back with the correct map. This happens when I set the time extent as shown, or if set as a property.
I do not want the map to fully re-render when changing the time extent. Is this possible with the wrapper? I cannot upgrade to React 19 at this time.
This was not an issue with the (half-broken) web map component nor using the JS SDK to create the map view.