6

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

2
  • does this return rather than running the next line? if (!view) return; Commented Jul 12, 2023 at 15:49
  • It does run the next line, but the function handleClick does not run when I click on the map Commented Jul 19, 2023 at 15:16

2 Answers 2

1
+50

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]);
...
Sign up to request clarification or add additional context in comments.

Comments

0

You are checking if view is falsy, then returning out of the hook, and that makes adding the event unreachable code.

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

The view variable is probably still null when handleClick is added, since it's set asynchronously in the loadMap function. Add a conditional around the code that adds and removes the event so it's only added when the view is available.

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

1 Comment

I didn't work, isn't it the same? if the view has not a falsy value it will not run the code inside the if

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.