使用 React Typescript 在 react-leaflet-markerclusterer 中显示所有集群标记
Show All Cluster Markers in react-leaflet-markerclusterer using React Typescript
我的 React Typescript 应用程序使用 react-leaflet
& react-leaflet-markerclusterer
显示带有标记簇的 Leaflet 地图。
但是,我无法让地图显示地图视图内的所有聚类标记。我正在尝试 convert this JS solution 到 Typescript。
中显示的错误之一。 JS 控制台是
React Hook "useMap" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function
在VSCode中,还有一个Typescript错误
Object is possibly 'undefined'.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>
)
}
这不是 typescript 问题,这是 react 问题。挂钩 need to be called either within the top level of the function body, or as part of another custom hook. The same applies to react-leaflet's useMap
. You can move it outside the useEffect
. However a useMap
hook call must be part of a component that is a child of the MapContainer
so that it has access to the leaflet context object. You can abstract this logic into its own component, like in this example,但我认为你最好使用带有状态变量的 whenCreated
来获取 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 兼容的正确 version of react-leaflet-markercluster。
我的 React Typescript 应用程序使用 react-leaflet
& react-leaflet-markerclusterer
显示带有标记簇的 Leaflet 地图。
但是,我无法让地图显示地图视图内的所有聚类标记。我正在尝试 convert this JS solution 到 Typescript。
中显示的错误之一。 JS 控制台是
React Hook "useMap" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function
在VSCode中,还有一个Typescript错误
Object is possibly 'undefined'.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>
)
}
这不是 typescript 问题,这是 react 问题。挂钩 need to be called either within the top level of the function body, or as part of another custom hook. The same applies to react-leaflet's useMap
. You can move it outside the useEffect
. However a useMap
hook call must be part of a component that is a child of the MapContainer
so that it has access to the leaflet context object. You can abstract this logic into its own component, like in this example,但我认为你最好使用带有状态变量的 whenCreated
来获取 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 兼容的正确 version of react-leaflet-markercluster。