I'm working on application where I'm displaying a map & multiple different locations with markers. These markers can be clicked in order to open simple dialog, which shows some information about that specific location. Here is code sample:
Mapping through array of locations & calling the function on each marker.
{markers && (
<>
{markers.map((marker, idx) => (
<MarkerDialog key={idx} marker={marker} />
))}
</>
)}
Adding dialog to marker.
const MarkerDialog = ({ marker }) => {
const [dialog, setDialog] = useState(false);
const handleClickOpen = () => {
setDialog(true);
};
const handleClose = () => {
setDialog(false);
};
const handleMarkerClick = (e, marker) => {
if (dialog) {
handleClose();
} else {
handleClickOpen();
}
};
return (
<div>
<Marker
position={marker.location}
icon={status(marker)}
eventHandlers={{
click: handleMarkerClick,
}}
/>
{dialog && (
<Dialog
marker={marker}
dialog={dialog}
handleClose={handleClose}
/>
)}
</div>
);
};
export default MarkerDialog;
This creates a problem if you click on multiple markers. In that case the dialogs stack on top of each other, because application never closes previous dialog.
If I click on marker and dialog opens, and then I'll go and click on another marker, I would like that previous dialog closes. How can I achieve this?
Lift the state up and maintain a selected index for the click of the marker.
MarkerDialog
const MarkerDialog = ({ marker, handleMarkerClick, handleClose,dialog }) => {
return (
<div>
<Marker
position={marker.location}
icon={status(marker)}
eventHandlers={{
click: handleMarkerClick
}}
/>
{dialog && (
<Dialog marker={marker} dialog={dialog} handleClose={handleClose} />
)}
</div>
);
};
export default MarkerDialog;
Parent
const [selectedMarkerIndex, setSelectedMarkerIndex] = useState(null);
const handleClose = () => {
setSelectedMarkerIndex(-1)
};
const handleMarkerClick = (e, marker,index) => {
/* Do stuff with e and marker */
setSelectedMarkerIndex(index)
};
{
markers && (
<>
{markers.map((marker, idx) => (
<MarkerDialog
key={idx}
marker={marker}
handleMarkerClick={(e, marker) => handleMarkerClick(e, marker, idx)}
handleClose={handleClose}
dialog={idx === selectedMarkerIndex}
/>
))}
</>
);
}