javascript - 使用 React Typescript 在 react-leaflet-markerclusterer 中显示所有集群标记
问题描述
react-leaflet
我的 React Typescript 应用程序使用& 显示带有标记集群的传单地图react-leaflet-markerclusterer
。
但是,我无法让地图显示地图视图内的所有集群标记。我正在尝试将此 JS 解决方案转换为 Typescript。
中显示的错误之一。JS 控制台是
不能在回调中调用 React Hook “useMap”。必须在 React 函数组件或自定义 React Hook 函数中调用 React Hooks
在 VSCode 中,还有一个 Typescript 错误
对象可能是“未定义”.ts(2532)
在线上
const groupBounds = group.getBounds();
为什么会发生这种情况,编写此 Typescript 代码的正确方法是什么?
import React, { useEffect, useRef } from 'react';
import { MapContainer, TileLayer, Marker, useMap } from 'react-leaflet';
import MarkerClusterGroup from 'react-leaflet-markercluster';
interface IProps {
markers: {
lat: number;
lon: number;
}[];
mapCenter: {
lat: number;
lon: number;
};
}
export function MapView({markers, mapCenter}: IProps): JSX.Element {
const groupRef = useRef();
useEffect(() => {
if (groupRef !== undefined) {
const group = groupRef.current;
const map = useMap(); // ERROR: React Hook "useMap" cannot be called inside a callback.
const groupBounds = group.getBounds(); // ERROR: Object is possibly 'undefined'.ts(2532)
map.fitBounds(groupBounds);
}
}, []);
return (
<MapContainer
center={[mapCenter.lat, mapCenter.lon]}
zoom={10}
style={{ width:'100%', height:'100vh' }}
className='markercluster-map'
>
<TileLayer
url={`https://api.mapbox.com/styles/v1/mapbox/streets-v11/tiles/{z}/{x}/{y}?access_token=${access_token}`}
/>
<MarkerClusterGroup ref={groupRef}>
{
markers.map((marker, index) => (
<Marker
position={[marker.lat, marker.lon]}
key={index}
/>
))
}
</MarkerClusterGroup>
</MapContainer>
)
}
解决方案
这不是打字稿问题,这是反应问题。钩子需要在函数体的顶层调用,或者作为另一个自定义钩子的一部分。这同样适用于 react-leaflet 的useMap
。你可以把它移到外面useEffect
。但是,useMap
钩子调用必须是作为子组件的一部分,MapContainer
以便它可以访问传单上下文对象。您可以将此逻辑抽象到它自己的组件中,就像在这个示例中一样,但我认为您最好使用whenCreated
带有状态变量的 a 来获取 的实例L.Map
并在效果中使用它:
export function MapView({markers, mapCenter}: IProps): JSX.Element {
const groupRef = useRef();
const [map, setMap] = useState();
useEffect(() => {
if (groupRef && map) {
const group = groupRef.current;
const groupBounds = group?.getBounds();
map.fitBounds(groupBounds);
}
}, [map, groupRef]);
return (
<MapContainer
whenCreated={map => setMap(map)}
moreProps={moreProps}
>
<Stuff />
</MapContainer>
)
}
如果 TS 仍在抱怨group
或map
未定义,您可以?.
对它们使用可选的属性运算符:
if (groupRef && map) {
const group = groupRef?.current;
const groupBounds = group?.getBounds();
map?.fitBounds(groupBounds);
}
Typescript 应该足够聪明,可以知道这一点groupRef
并被map
定义,因为它们在if
声明中,但它可能仍然会抱怨group
被定义。您也可以if (groupRef && groupRef.current && map)
消除所有疑虑。
**注意:确保您使用的是与 react-leaflet v3 兼容的正确版本的 react-leaflet-markercluster。
推荐阅读
- arrays - 使用 .map 而不是 For-loop 来解开数组 Swift 中的数组?
- javascript - 正确识别来自 URL 的参数
- kotlin - Ktor 中带有 KeyCloak 的 OAuth:它应该像这样工作吗?
- java - Splitting Strings in java without removing the match
- .net - 将文件编译到库中并访问它,但不能作为资源
- xml - Apply-Template 仅适用于 ID 基于父子节点列表的节点
- winapi - 如何捕获菜单栏的激活?
- firebase - google_sign_in 包中的 getServerAuthToken 返回 null
- php - 如何在 Windows 中通过 PHP 运行后台进程?
- okhttp - 如何重现 OkHttp 的错误