You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React-leaflet中实现点击Marker后调整右侧列表排序?

实现点击Marker置顶对应列表项的方案

核心思路

  1. 统一在App组件中管理地图点位数据,避免Map和List重复请求Firestore导致的数据不一致
  2. 使用文档ID作为选中标识(比索引更可靠,不会因排序变化失效)
  3. 在List组件中根据选中ID重新排序数组,将选中项移至首位

修改后的代码

App.js

import { useState, useEffect } from 'react';
import { query, collection, onSnapshot } from 'firebase/firestore';
import { db } from './firebase'; // 请替换为你的Firebase配置文件路径

function App() {
  const [houses, setHouses] = useState([]);
  const [selectedHouseId, setSelectedHouseId] = useState(null);

  // 仅在App组件中请求一次Firestore数据
  useEffect(() => {
    const q = query(collection(db, "map-markers"));
    const unsubscribe = onSnapshot(q, (querySnapshot) => {
      const houseData = querySnapshot.docs.map(doc => ({
        id: doc.id,
        ...doc.data()
      }));
      setHouses(houseData);
    });
    // 组件卸载时清理Firestore订阅
    return unsubscribe;
  }, []);

  return (
    <div className="App">
      <Header />
      <div className="map-content">
        <Map houses={houses} onSelect={setSelectedHouseId} />
        <List houses={houses} selectedHouseId={selectedHouseId} />
      </div>
    </div>
  );
}

Map.js

import { Marker, MapContainer, TileLayer } from 'react-leaflet';

const Map = ({ houses, onSelect }) => {
  // 替换为你的地图中心坐标
  const center = [39.9042, 116.4074];

  return (
    <div style={{ width: "100%" }}>
      <MapContainer
        center={center}
        zoom={13}
        scrollWheelZoom={false}
        style={{ height: "100vh" }}
      >
        <TileLayer
          attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        />
        {houses.map((house) => (
          <Marker
            key={house.id}
            eventHandlers={{
              click: () => {
                onSelect(house.id); // 传递选中点位的文档ID
              },
            }}
            position={[parseFloat(house.lat), parseFloat(house.lon)]}
            icon={defaultIcon}
          />
        ))}
      </MapContainer>
    </div>
  );
};

List.js

const List = ({ houses, selectedHouseId }) => {
  // 排序逻辑:将选中项移至数组首位
  const sortedHouses = [...houses];
  if (selectedHouseId) {
    const targetIndex = sortedHouses.findIndex(house => house.id === selectedHouseId);
    if (targetIndex !== -1) {
      const selectedItem = sortedHouses.splice(targetIndex, 1)[0];
      sortedHouses.unshift(selectedItem);
    }
  }

  return (
    <div style={{ width: "50%" }}>
      {sortedHouses.map((house) => (
        <ListItem key={house.id} title={house.title} />
      ))}
    </div>
  );
};

关键优化点

  • 减少重复请求:避免Map和List各自请求Firestore数据,提升性能并保证数据一致性
  • 可靠的选中标识:使用Firestore文档ID代替数组索引,防止因数组排序导致的选中错误
  • 高效排序逻辑:通过splice和unshift操作快速调整选中项位置,保持其余项原顺序
  • 内存泄漏防护:在App组件中清理Firestore实时订阅,避免组件卸载后无效监听

内容的提问来源于stack exchange,提问作者userName

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 20:36:23