如何在React-Leaflet项目中点击workout容器修改地图中心点
问题描述
我希望通过点击携带坐标属性的workout容器对象,修改React-Leaflet地图容器的中心点,已使用Context API实现全组件状态共享,相关代码如下:
WorkoutData.js
export const WorkoutsData = [ { id: 1, coords: { latitude: 56.27360151291927, longitude: -82.84886256490017 }, }, { id: 2, coords: { latitude: 49.27360151291927, longitude: -75.84886256490017 }, }, { id: 3, coords: { latitude: 39.27360151291927, longitude: -79.84886256490017 }, } ];
MapLocation.js
状态变量统一存放在main.js中,所有组件通过Context API共享状态:
import React, { useEffect, useState } from "react"; import "./styles.css"; import { WorkoutsData } from "./WorkoutLocation"; const MapLocation() => { const [workouts, setWorkouts] = useState(WorkoutsData); const [changedCoords, setChangedCoords] = useState({latitude: 0, longitude: 0}) const [workoutsClicked, setWorkoutsClicked] = useState(false); const locateWorkout = (id) => { setWorkoutsClicked(true) const findLocation = workouts.find((exercise) => { return exercise.id === id; }); setChangedCoords({ latitude: findLocation.coords.latitude, longitude: findLocation.coords.longitude }) } return( <> workouts.map((workout) => { return( <div key = {workout.id} className = 'workout-info'> <div className = "workout-details"> <p>{workout.coords}</p> </div> </div> ) }) </> ) } export default MapLocation;
Map.js
const Map = () => { const[initialCoords, setInitialCoords] = useState({latitude: 0, longitude: 0}) useEffect(() => { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition((position) => { setInitialCoords({ latitude: position.coords.latitude, longitude: position.coords.longitude }) }) } }, []) return( <> <MapContainer center = { workoutsClicked !== true ? [initialCoords.latitude, initialCoords.longitude] : [changedCoords.latitude, changedCoords.longitude]} zoom = {20}> <TileLayer attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"/> </MapContainer> </> ) } export default Map
解决方案
当前代码存在两个核心问题,按如下步骤修复即可:
- MapLocation组件没有给workout容器绑定点击事件,点击不会触发坐标更新逻辑
- React-Leaflet的
MapContainer的center属性仅在组件初始化时生效,后续修改center值不会触发地图重定位,需要配合useMap钩子主动更新视图
步骤1:全局状态同步
将changedCoords、workoutsClicked、locateWorkout、workouts这些共享状态和方法全部移到main.js的Context中,确保MapLocation和Map组件都能正常调用/读取。
步骤2:修复MapLocation组件的点击绑定
给workout容器添加onClick事件,触发坐标更新:
// MapLocation.js 修改后渲染逻辑 return( <> {workouts.map((workout) => { return( <div key={workout.id} className='workout-info' {/* 绑定点击事件,调用全局的locateWorkout */} onClick={() => locateWorkout(workout.id)} > <div className="workout-details"> <p>纬度:{workout.coords.latitude},经度:{workout.coords.longitude}</p> </div> </div> ) })} </> )
步骤3:修复Map组件的中心点更新逻辑
新增一个子组件封装useMap逻辑,监听坐标变化主动调用setView更新地图中心点:
// Map.js 修改后代码 import { MapContainer, TileLayer, useMap } from 'react-leaflet' // 新增地图中心点更新子组件 function MapCenterUpdater({ center, zoom }) { const map = useMap() useEffect(() => { map.setView(center, zoom) }, [center, zoom, map]) return null } const Map = () => { const[initialCoords, setInitialCoords] = useState({latitude: 0, longitude: 0}) // 替换为你自己的Context引入名,读取共享状态 const { workoutsClicked, changedCoords } = useYourContext() useEffect(() => { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition((position) => { setInitialCoords({ latitude: position.coords.latitude, longitude: position.coords.longitude }) }) } }, []) const mapCenter = workoutsClicked ? [changedCoords.latitude, changedCoords.longitude] : [initialCoords.latitude, initialCoords.longitude] return( <MapContainer center={mapCenter} zoom={20}> {/* 新增中心点更新组件,监听center变化自动更新 */} <MapCenterUpdater center={mapCenter} zoom={20} /> <TileLayer attribution='© OpenStreetMap contributors' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> </MapContainer> ) } export default Map
内容的提问来源于stack exchange,提问作者prakash subba
相关产品推荐
相关产品推荐

