javascriptreactjstypescriptarcgis-js-api

Add onClick handler to MapView in React?


I'm using the ArcGIS API for JavaScript to display a map and I want to get the selected feature when someone clicks on the map. This is my MapComponent

export const MapComponent = () => {
    const elementRef = useRef(null);
    const [view, setView] = useState<MapView>();
    const [selected, setSelected] = useState<Feature>();


    const handleClick = useCallback((e: any) => {
        if (!view) return;
        view.hitTest(e)
            .then(res => {
                if (res.results.length > 0) {
                    const feature = res.results[0];
                    if (feature.type === 'graphic') {
                        setSelected(feature.graphic.attributes)
                    }
                }
            })
    }, [view]);

    useEffect(() => {
        if (!view) return;
        const handle = view.on('click', handleClick)
        return handle && handle.remove();
    }, [view]);

    useEffect(() => {
        const loadMap = async () => {
            const { init } = await import('./Map');
            const mapView = init(elementRef.current);
            setView(mapView);
        }
        loadMap()
        return () => view && view.destroy();
    }, []);

    return (
        <>
            <div
                ref={elementRef}
                style={{ height: '500px', width: '800px' }}
            >
            </div>
            <pre>{JSON.stringify(selected, null, 2)}</pre>
        </>
    )
}

I initialized the map in a useEffect and save the map view with useState, I saw in the documentation you have to add your event handlers on another useEffect and I tried to do that, but the function handleClick doesn't run when I click on the map


Solution

  • It seems like you’re trying to add an event listener to the map view to handle clicks and get the selected feature. From the code you provided, it looks like you’re correctly adding the event listener in a useEffect hook and using the hitTest method to get the clicked feature.

    One thing you could try is to add a console.log statement inside the handleClick function to see if it’s being called when you click on the map. If it’s not being called, there might be an issue with how the event listener is being added to the map view.

    You could also try moving the handleClick function definition inside the useEffect hook where you’re adding the event listener, to make sure that it has access to the latest view state.

    ...
        const selectFeature = (selection: __esri.HitTestResult) => {
            console.debug(selection.results[0])
        }
    
        useEffect(() => {
            if (!view) return;
            const eventHandler = (e: __esri.ViewClickEvent) => {
                view.hitTest(e)
                    .then(selectFeature)
                    .catch(console.error)
            }
    
            const handler = view.on('click', eventHandler);
    
            return () => handler.remove();
        }, [view]);
    ...