React-Leaflet 多层中的相同标记

React-Leaflet same marker in multiple Layers

如何在 react-leaflet 的多个图层中添加相同的标记?

例如:

我有一个应用程序可以用 React 传单搜索餐厅,每个标记都是不同的餐厅。我想要一个 LayerControl 来按类型和评级(1..5 星)过滤它们。

我可以使用 LayerControl.Overlay 按类型(例如自助餐)进行过滤,但我还想按评级进行过滤。如果我有一家餐厅类型='buffet' 和评级=4,我该如何做才能仅在选中自助餐类型和 4 星评级时显示标记。

这是我的 current code,仅按类型过滤。

我正在使用 react-leaflet v3。

您使用的创建各种图层组来管理过滤器的方法并不是最好的方法。我采取了另一种方法。

使用所需过滤器创建状态对象

在您的应用中,创建一个包含潜在过滤器的状态变量。我们将其设置为最初包含所有选项:

const restaurantTypes = ["Family Style", "Buffet", "Fast Food", "Cafe"];
const ratings = [1, 2, 3, 4, 5];

function App() {
  const [filters, setFilters] = useState({
    restaurantTypes,
    ratings
  });
  ...
}

自定义过滤器组件

我选择创建一个自定义组件,它基本上与传单层控件完全相同 html 标记,但没有任何功能。您可以查看此答案末尾的沙箱,但它所做的只是管理我们刚刚定义的 filters 状态变量。这是一个简短的总结:

const FilterControl = ({ filters, setFilters }) => {
  return (
    <div>
      <h3>Type</h3>
      {restaurantTypes.map((type) => (
        <label>
          <input
            type="checkbox"
            checked={filters.restaurantTypes.includes(type)}
            onClick={(e) => {
              if (filters.restaurantTypes.includes(type)) {
                setFilters((prevFilters) => ({
                  ...prevFilters,
                  restaurantTypes: prevFilters.restaurantTypes.filter(
                    (f) => f !== type
                  )
                }));
              } else {
                setFilters((prevFilters) => ({
                  ...prevFilters,
                  restaurantTypes: [...prevFilters.restaurantTypes, type]
                }));
              }
            }}
          />
          <span>{type}/span>
        </label>
      ))}
      <h3>Rating</h3>
      {ratings.map((rating) => (
        // same as above but for ratings
      ))}
    </div>
  );
};

所以现在你的 FilterControl 可以巧妙地管理 filters 的状态。

根据过滤器过滤标记

现在您所要做的就是映射您的 restaurants 数据集,并且只渲染 typerating 在当前 filters 中的标记:

function App() {
  const [filters, setFilters] = useState({
    restaurantTypes,
    ratings
  });
  return (
    <MapContainer ... >
      <TileLayer ... />
      <FilterControl filters={filters} setFilters={setFilters} />
      {restaurants.map((restaurant) => {
        if (
          filters.restaurantTypes.includes(restaurant.type) &&
          filters.ratings.includes(restaurant.rating)
        ) {
          return <Marker position={restaurant.coordinates} />
        }
        return null;
      })}
    </MapContainer>
  );
}

Working codesandbox