skip to Main Content

Inside useEffect, the useState Boolean value does not change. Please help me.
I’m trying to make a modal window pop up when a marker is clicked in the openlayers map. Since the openlayers map is executed inside useEffect, the marker click event must also be inside useEffect, but even if setState is executed, a boolean value does not come out. When debugging, it is confirmed that the boolean value has changed, but when taking a console.log, the value does not change and the modal window does not appear. Please help me.

function App() {
  const [mapObject, setMapObject] = useState({});
  const [modalState, setModalState] = useState(false);

  useEffect(() => {
    const map = new OlMap({
      layers: [
        new TileLayer({
          source: new OSM(),
        }),
      ],
      target: "map",

      view: new View({
        center: fromLonLat([126.752, 37.4713]),
        zoom: 7,
        minZoom: 3,
        maxZoom: 17,
      }),
    });

    jsondata.forEach((dataPoint) => {
      const { lat, log } = dataPoint;

      const coordinate = fromLonLat([lat, log]);

      const markerFeature = new Feature({
        geometry: new Point(coordinate),
      });

      const markerStyle = new Style({

      });

      const vectorLayer = new VectorLayer({
        source: new VectorSource(),
      });

      markerFeature.setStyle(markerStyle);
      vectorLayer.getSource().addFeature(markerFeature);

      map.addLayer(vectorLayer);

      // const handleMarkerClick = (event) => {
      //   setModalState(true);
      // };

      const handleMarkerClick = () => {
        setModalState((modalState) => !modalState);
        console.log("핸들러에서 모달 : " + modalState);
      };

      map.on("click", function (event) {
        var feature = map.forEachFeatureAtPixel(
          event.pixel,
          function (feature) {
            return feature;
          }
        );
        if (feature === markerFeature) {
          handleMarkerClick();
          console.log("modalState : " + modalState);
        }
      });
    });


    setMapObject({ map });

    return () => {
      map.setTarget(null);
      setMapObject(null);
    };
  }, []);

  return (
    <div>
      {/* <Modal modalProps={modalState}>
      </Modal> */}
      
      {modalState && (
        <ReactModal>
          <button onClick={() => setModalState(false)}>닫기</button>
        </ReactModal>
      )}
    </div>
  );
}

I’m trying to make a modal window pop up when a marker is clicked in the openlayers map.

2

Answers


  1. function App() {
      const modalStateRef = useRef()
      const [modalState, setModalState] = useState(false);
      modalStateRef.current = modalState;
    
      useEffect(() => {
        // ...
        
        map.on("click", function (event) {
          var feature = map.forEachFeatureAtPixel(
            event.pixel,
            function (feature) {
              return feature;
            }
          );
          if (feature === markerFeature) {
            handleMarkerClick();
            /* 👉 everywhere inside `useEffect`,
             * replace `modalState` with `modalStateRef.current`
             */
            console.log("modalState : " + modalStateRef.current);
          }
        });
      }, [])
      
      // ...
    }
    

    This is a classic "React stale closure" problem. You can resolve it with useRef hook. See my other answer for more in-depth explanation why useRef works

    Login or Signup to reply.
  2. When debugging, it is confirmed that the boolean value has changed, but when taking a console.log, the value does not change

    In fact, with the way you are console logging if you see it didn’t change that means it is changed, here since the function is supposed to toggle the state boolean value, you are looking to the opposite. see here

    you’ve mentioned

    I’m trying to make a modal window pop up when a marker is clicked in the openlayers map.

    you just do this?

    const handleMarkerClick = () => {
       setModalState(true);
    };
    

    you don’t really have to toggle the state if you want the modal to be open, and you just set it to false when you want to hide it.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search