您用于创建各种图层组来管理过滤器的方法并不是最好的方法。我采取了另一种方法。
使用所需的过滤器创建一个状态对象
在您的应用中,创建一个包含潜在过滤器的状态变量。我们将其设置为最初包含所有选项:
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 数据集,并且只渲染type 和rating 在当前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>
);
}