1

I am showing a world map in react using highcharts and I am showing lot of bubbles(data points) on the map. When the user clicks zoom in button, the map takes some time to zoom in with large number of bubbles on the map. I want to add a loading message when the map is zooming in so that the user doesnt click the zoom in button again and again. I am trying to add a function for onClick on zoomin button as below, where I set a state for the loader and toggle it. However I see, once the loader goes away, the map is reset to its original size

const options = useMemo(
...
mapNavigation: {
        enabled: true,
        enableButtons: true,
        enableMouseWheelZoom: false,
        enableDoubleClickZoom: true,
        buttons: {
          zoomIn: {
            onclick: function () {
              
              setZoomLoad(true) //setting loader state
              const chart = this as any              
              setTimeout(() => { setZoomLoad(false); chart.mapZoom(0.5); }, 3000)
            }
          }
        }
      }

return (zoomLoad) ? (
    <div>Loading...</div>
  ) : (
    <WorldMapComp options={options} chartRef={chartRef} />
  )

I also tried setting a useEffect with redraw to check if will render the map with zoom like below , which didnt work

useEffect(() => {
    // After re-rendering, restore the zoom level
    if (chartRef) {
      chartRef.current.chart.mapZoom = 0.5 as any;
      chartRef.current.chart.redraw();
    }
  }, []);
ChandyP
  • 11
  • 1

1 Answers1

0

In your useEffect function,it should be

 chartRef.current.chart.mapZoom(0.5) 

instead of

 chartRef.current.chart.mapZoom = 0.5. 

The reason it doesn't work in your onClick function is because React render is asynchronous. In this instance it looks like it is re-rendering after you have already called the mapZoom function erasing the effect. That is why you lost that zoom change.

You should be able to get around needing to use useEffect by adding an await.

onclick: async function () {
          setZoomLoad(true) //setting loader state
          const chart = this as any              
          await setTimeout(() => { setZoomLoad(false); },3000)
          chart.mapZoom(0.5);
        }

Also see: Where does the function continue after a re-render?

Zarek
  • 56
  • 4
  • I have added ` onclick: function () { setZoomLoad(true) const chart = this as any setTimeout(() => { setZoomLoad(false); setZoomLevel(0.5); }, 3000) } ` and also a useEffect ` useEffect(() => { // After re-rendering, restore the zoom level if (chartRef) { chartRef.current.chart.mapZoom = zoomLevel as any; chartRef.current.chart.redraw(); } }, [zoomLevel]); ` I still see the map is rendering with original zoom only – ChandyP Jul 09 '23 at 16:50
  • Thanks for help with mapZoom function syntax, I needed the rerender using usEffect because the map was reset to original once the loader is gone and didnt have the zoomed in effect. I was able to get it working by storing the zoom level and center in a state and using it in the useEffect. Below are my changes `onclick: function () { const chart = this as any; setCenter(chart.mapView.center); setZoomLoad(true); setTimeout(() => {setZoomLoad(false);setZoomLevel(curr=>return curr/2 },1000) }` And for the useEffect `chartRef.current,chart.mapZoom(zoomLevel,center[0],center[1])` – ChandyP Jul 14 '23 at 07:11