首页 > 解决方案 > 使用 react 和 mapbox gl 或 maplibre gl 动态加载标记

问题描述

我正在学习反应。我想显示一个动态显示和隐藏标记的地图。这行得通。我使用Maplibre GL,它是Mapbox GL的一个分支,处理方式是相同的。

然而不幸的是,当标记改变时,地图会重新加载,因为在useEffect-Hook 中指定了依赖项。然而,没有它,标记不会改变。我无法访问 . 之外的地图(可变地图)useEffect。有什么可能性可以防止重新加载地图,而是动态调整标记。

这是我的代码:

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;

标签: reactjsreact-hooksuse-effectmapbox-glmaplibre-gl

解决方案


推荐阅读