react-leaflet使用useRef调用flyTo时返回undefined如何解决
问题原因
你的代码中MapContainer被包裹在width && height的条件渲染逻辑中,只有当useResizeDetector获取到外层容器的宽高后,地图组件才会完成挂载,whenCreated回调才会触发给mapRef.current赋值。而你当前把触发按钮放在了条件渲染分支外,地图未挂载时按钮就可以被点击,此时mapRef.current自然是undefined。
解决方案
- 将按钮移动到条件渲染的代码块内,保证只有地图加载完成后按钮才会展示,避免用户提前点击
- 给外层容器设置最小高度,避免
useResizeDetector无法正常获取宽高导致地图始终不渲染 - 可增加加载状态提示,优化宽高未获取到时的用户体验
修改后的核心代码示例
import React, { VFC, useRef } from "react" import { useResizeDetector } from 'react-resize-detector'; import { MapContainer, TileLayer, CircleMarker, Popup } from 'react-leaflet' import { MapDatum } from "./types" import L from 'leaflet' import { Button } from "@material-ui/core"; type MapProps = { mapData: MapDatum[] } export const MapContent: VFC<MapProps> = ({ mapData }) => { const { ref, width, height } = useResizeDetector() // 初始化ref时明确指定类型和初始值 const mapRef = useRef<L.Map | null>(null) const disneyLandLatLng = {lat:33.8121, lng:-117.9190} function handleOnFlyTo() { // 兜底判断避免报错 if (!mapRef.current) return mapRef.current.flyTo(disneyLandLatLng, 14, { duration: 2 }); } return ( // 增加最小高度保证resize detector能正常获取尺寸 <div ref={ref} style={{ width: "100%", height: "100%", minHeight: "500px" }}> {width && height ? ( <> <Button onClick={handleOnFlyTo}>Fly</Button> <MapContainer style={{ width: "100%", height: "100%" }} bounds={[[-180, -270], [180, 270]]} center={[0, 0]} zoom={1} scrollWheelZoom={true} attributionControl={false} whenCreated={ mapInstance => { mapRef.current = mapInstance }} > <TileLayer attribution="" url="https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png" /> {mapData.map(({ label, lon, lat, r, color }, i) => ( <CircleMarker key={i} center={[lat, lon]} radius={r} fillColor={color} stroke={false} fillOpacity={.6} > <Popup> {label} </Popup> </CircleMarker> ))} </MapContainer> </> ) : ( <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%' }}> 地图加载中... </div> )} </div> ) }
内容的提问来源于stack exchange,提问作者Katsuki
相关产品推荐
相关产品推荐

