I am learning React. I want to display a map on which markers are dynamically shown and hidden. This works. I use Maplibre GL, which is a fork of Mapbox GL and the handling is the same.
Unfortunately, however, when the markers are changed, the map is reloaded because a dependency is specified in the useEffect
-Hook. Without it, however, the markers do not change. I cannot access the map (variable map) outside of useEffect
.
What possibilities are there to prevent the map from being reloaded, but to adjust the markers dynamically.
This is my code:
import React from "react";
import maplibregl from "maplibre-gl";
const App = () => {
const pois = [
{
display_name: "backery a",
icon: "https://nominatim.openstreetmap.org/ui/mapicons//shopping_bakery.p.20.png",
lat: "50.4",
lon: "7.1",
importance: "0.111",
geojson: '{"type":"Point","coordinates":[7.1,50.4]}',
place_id: "1",
},
{
display_name: "backery b",
icon: "https://nominatim.openstreetmap.org/ui/mapicons//shopping_bakery.p.20.png",
lat: "51.4",
lon: "6.1",
importance: "0.211",
geojson: '{"type":"Point","coordinates":[6.1,51.4]}',
place_id: "2",
},
];
const [searchTerm, setSearchTerm] = React.useState(
localStorage.getItem("search") || "backery a"
);
React.useEffect(() => {
localStorage.setItem("search", searchTerm);
}, [searchTerm]);
const handleSearch = (event) => {
setSearchTerm(event.target.value);
};
const searchedpois = pois.filter((poi) =>
poi.display_name.toLowerCase().includes(searchTerm.toLowerCase())
);
return (
<div>
<h1>React Maplibre Map</h1>
<Search searchValue={searchTerm} onSearch={handleSearch} />
<hr />
<List list={searchedpois} />
<hr />
<Map list={searchedpois} />
</div>
);
};
const Map = (props) => {
React.useEffect(() => {
const map = new maplibregl.Map({
container: "map",
style:
"https://api.maptiler.com/maps/streets/style.json?key=mykey",
center: [7.5, 50.1],
zoom: 4,
});
map.on("load", () => {
props.list.map((item) =>
new maplibregl.Marker().setLngLat([item.lon, item.lat]).addTo(map)
);
});
}, [props.list]);
return <div></div>;
};
const Search = ({ searchValue, onSearch }) => (
<div>
<label htmlFor="search">Suche: </label>
<input id="search" type="text" onChange={onSearch} value={searchValue} />
</div>
);
const List = (props) => (
<div>
<table>
<tbody>
{props.list.map((item) => (
<POI key={item.place_id} poi={item} />
))}
</tbody>
</table>
</div>
);
const POI = ({ poi }) => (
<tr key={poi.place_id}>
<td>{poi.display_name}</td>
<td>{poi.lat}</td>
<td>{poi.lon}</td>
<td>{poi.importance}</td>
<td>
<img alt="" src={poi.icon} />
</td>
</tr>
);
export default App;