Siri
Siri

Reputation: 129

state change is not reflected inside useEffect [map.on('click') mapbox]

I'm trying to conditionally do some work inside useEffect. Here, I'm using mapbox and react hooks.

What I'm trying to do is if a state variable is "a" for example, I want to show popup on clicking on the markers. if not "a", I don't want to show popup.

My 1st try:

useEffect(() => {
    map.on('click', 'markers', (e) => {
        if (value === "a") {
            console.log('aaa');
            new mapboxgl.Popup()
                .setLngLat(coordinates)
                .setHTML(`<div>popup</div>`)
                .addTo(map);
        }
        else {
            // other work ... but not showing popup 
            console.log('bbb');
            console.log('other works work');
        }
    });
}, [value]);

The result is wired because 3 of console.logs are logged to the console everytime I clicked on the markers.

// aaa
// bbb
// other works work

The state is working well. How can I achieve this?

I've tried to research online and tried the below as well. not working. same result as above.

useEffect(() => {
    map.on("click", "markers", (e) => { myfun(e); });
}, [value]);

const myfun = useCallback(
   (e) => {
      if (value === "a") {
        console.log('aaa');
        new mapboxgl.Popup()
           .setLngLat(coordinates)
           .setHTML(`<div>popup</div>`)
           .addTo(map);
      } else {
        // other work ... but not showing popup 
        console.log('bbb');
        console.log('other works work');
      }
    },
    [value]
  );

First page load, the initial value of value is a, I can see just the popup. (which is fine). Then I change the sate and it becomes NOT a, I start to see popup and also work from the else block. I just want to see else block working.

Also tried this.

useEffect(() => {
    if (value === "a") {
        map.on("click", "markers", (e) => {
            // show popup
        }
    }
    else {
        map.on("click", "markers", (e) => {
            // do other works
        }
    }

}, [value]);

Upvotes: 0

Views: 575

Answers (1)

Andrew Yohanes
Andrew Yohanes

Reputation: 11

Use the cleanup function in useEffect and it will work fine
Example:

useEffect(() => {
  map.on('click', 'markers', onClickHandler);

  return () => {
    map.off('click', 'markers', onClickHandler);
  }
}, [map, value])

Sources:
How to disable an event listener in mapbox?
https://blog.logrocket.com/understanding-react-useeffect-cleanup-function/

Upvotes: 1

Related Questions