Reputation: 385
I am creating a google maps react application where i can create, edit and remove objects from then map. When i press a marker the google map click listener will display its data in a form where i can edit it. If i do start editing the data in my form i set the "isEditingMapObject" state too true. This is done with useContext.
Now my goal is to prevent other click listeners to run their code when "isEditingMapObject" state is true. I figured this would be easy with a if check. But it seems the click listeners "isEditingMapObject" state never changes. It will always stay false.
const Markers = ({ googleMap, map }) => {
const mapContext = useContext(MapContext);
const mapMarkerReducer = (state, action) => {
switch (action.type) {
case "ADD":
return state.concat(action.payload.marker);
case "UPDATE":
return state.filter(marker => marker._id !== action.payload._id).concat(action.payload.marker);
case "SET":
return action.payload;
case "REMOVE":
return state.filter(marker => marker._id !== action.payload._id);
default:
return state;
}
}
const [markers, markersDispatch] = useReducer(mapMarkerReducer, []);
useEffect(() => {
if (!googleMap || !map) {
return;
}
axios
.get(constants.API_MARKERS)
.then(result => {
console.log("success");
const markersLoaded = [];
for (const marker of result.data) {
const iconPath = marker.type == "info" ? iconImportant : iconMailbox;
const markerObj = new googleMap.maps.Marker({
zIndex: 115,
position: { lat: marker.latitude, lng: marker.longitude },
icon: {
url: iconPath,
scaledSize: new googleMap.maps.Size(15, 15)
},
type: "marker",
marker: marker,
map: map,
visible: mapContext.markersIsVisible
});
googleMap.maps.event.addListener(markerObj, "click", (marker) => {
if(mapContext.isEditingMapObject) {
return;
}
mapContext.setActiveMapObjectHandler(marker);
});
markersLoaded.push(markerObj)
}
markersDispatch({ type: "SET", payload: markersLoaded });
})
.catch(error => {
console.log(error.response);
});
}, [googleMap, map]);
return null
};
export default Markers;
I expected the if statement to trigger return when state of mapContext.isEditingMapObject is true. But it is always false inside the listener. When logging state outside of the listener, mapContext.isEditingMapObject is showing correct value.
Upvotes: 1
Views: 637
Reputation: 385
The map listener is storing the state when declared. And is not referencing to the same object as react state is. Therefore any changes in react state will have no effect on the listener.
workaround solution was to update react state when lister is triggered. And then use useEffect to trigger on that state change. In there i then access the current react state. Its not pretty! I have found no other working solution:
const [clickedMapObjectEvent, setClickedMapObjectEvent] = useState(null);
googleMap.maps.event.addListener(markerObj, "click", (marker) => {
//Can not access react state in here
setClickedMapObjectEvent(marker);
});
useEffect(() => {
//Access state in here
}, [clickedMapObjectEvent])
Upvotes: 2