如何在 react-leaflet 中使用 Typescript 设置对 'leafletElement' 的引用?
How to set the reference to the 'leafletElement' using Typescript inside react-leaflet?
问题是在我的 React 项目中使用 TS 时,我需要设置 useRef()
函数的类型,但我不知道它是什么。因此,在下面的代码中,我将其设置为 any
,然后调用 leafletElement
。出现的问题是即使在通过 whenCreated
函数 iside MapContainer
.
引用地图后,元素始终未定义
我试图以一种显示所有 Marker
的方式设置 MapContainer
使其动态调整大小,因此当位置更改时它会更新它并调整 MapContainer
因为它没有 ref
属性.
Example I'm trying to reproduce
const MapTry = () => {
const [nodes, setNodes] = useState<INode[]>([]);
const [devices, setDevices] = useState<IDevice[]>([]);
const [nodeDeviceTest, deviceNodeConnection] = useState([]);
var arrObj: any = [];
var arrOfBounds: any = [];
var mapRef = useRef<any>();
var groupRef = useRef<any>();
var device = new L.Icon({
iconUrl: deviceCar,
iconSize: [30, 30],
iconAnchor: [16, 3],
popupAnchor: [1, -1],
shadowSize: [41, 41]
});
var deviceNode = new L.Icon({
iconUrl: nodeDevice,
iconSize: [20, 30],
iconAnchor: [10, 0],
popupAnchor: [1, -34],
shadowSize: [41, 41],
})
useEffect(() => {
async function fetchData() {
const user = checkUserData();
const project = checkProjectData();
debugger;
if (mapRef.current && mapRef) {
let map = mapRef.current.leafletElement;
let group = groupRef.current.leafletElement;
map.fitBounds(group.getBounds());
}
const result = await getProjectNodeDeviceMap(project, user);
console.log(result);
if (result) {
if (result.devicesToNodes) {
for (var i = 0; i < result.devicesToNodes.length; i++) {
var objec = {
nodeId: "",
devId: "",
deviceLat: 0,
deviceLong: 0,
nodeLat: 0,
nodeLong: 0
}
for (var j = 0; j < result.devices.length; j++) {
if (result.devicesToNodes[i].deviceId == result.devices[j].deviceId) {
objec.deviceLat = result.devices[j].latitude
objec.deviceLong = result.devices[j].longitude
objec.devId = result.devices[j].deviceId
arrOfBounds.push([result.devices[j].latitude, result.devices[j].longitude])
for (var k = 0; k < result.nodes.length; k++) {
if (result.devicesToNodes[i].nodeId == result.nodes[k].id) {
objec.nodeLat = result.nodes[k].latitude
objec.nodeLong = result.nodes[k].longitude
objec.nodeId = result.nodes[k].id
arrOfBounds.push([result.nodes[k].latitude, result.nodes[k].longitude])
arrObj.push(objec);
break;
}
}
}
}
deviceNodeConnection(arrObj);
}
}
if (result.nodes) {
result.nodes.map((node: INode) => {
if (node.state == "running") {
node.color = "success";
}
else if (node.state == "error") {
node.color = "danger";
}
else if (node.state == "stopped") {
node.color = "warning";
}
else {
node.color = "info";
}
})
}
setNodes(result.nodes)
setDevices(result.devices)
}
}
const timer = setInterval(() => {
fetchData();
}, 3000)
return () => clearTimeout(timer);
}, [arrObj])
return (
<div className="col-md-9">
<div className="card shadow p-3 mb-5 bg-white rounded">
<div className="text-center">
<h3>Showcase</h3>
</div>
{devices && devices.length > 0 && <MapContainer
whenCreated={mapInstance => { mapRef.current = mapInstance }}
center={[devices[0].latitude, devices[0].longitude]}
zoom={6}
scrollWheelZoom={true}
minZoom={2}
maxBoundsViscosity={1.0}
zoomControl={false}
style={{ backgroundColor: "inherit", width: "100%", height: "60vh" }}
>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{nodeDeviceTest.length > 0 && nodeDeviceTest?.map((point: any) => {
return <Polyline key={point.deviceId} positions={[
[point.nodeLat, point.nodeLong], [point.deviceLat, point.deviceLong]
]} color={'blue'} dashArray="5,10" />
})}
<FeatureGroup ref={groupRef}>
{nodes?.map((point: any) => (
<Marker
zIndexOffset={100}
icon={deviceNode}
key={point.Id}
position={[
point.latitude,
point.longitude
]}
>
<Popup>
<br />
Node: {point.name}
<br />
State:
<span className={`text-${point.color}`}>
<b>{point.state}</b>
</span>
</Popup>
</Marker>
))}
{devices?.map((dev: any) => {
return <Marker
key={dev.deviceId}
position={[
dev.latitude,
dev.longitude
]}
icon={device}
>
<Popup>
Device id: {dev.deviceId}
</Popup>
</Marker>
})}
</FeatureGroup>
</MapContainer>}
</div>
</div>
)}
此外,如果我在解释中遗漏了什么,我希望 FeatureGroup
是正确的 referenced.Sorry。我是 React/TS.
的新手
编辑:这是我创建的示例代码
const Mapp = () => {
const devices = [{
deviceId: "1-528a-4f80-9c7a-124108f86895",
latitude: 45.5,
longitude: 18.7
},
{
deviceId: "2-528a-4f80-9c7a-124108f86895",
latitude: 60.5,
longitude: 18.7
}]
const nodes = [{
id: "test-node-1",
latitude: 45,
longitude: 15.4566,
name: "TestNode1",
state: "running",
},
{
id: "test-node-2",
latitude: 47,
longitude: 15.4566,
name: "TestNode2",
state: "running",
}]
const devicesToNodes = [{
deviceId: "1-528a-4f80-9c7a-124108f86895",
nodeId: "test-node-1"
},
{
deviceId: "2-528a-4f80-9c7a-124108f86895",
nodeId: "test-node-1"
}]
const arrOfLatLang = [{
deviceLat: 45.5,
deviceLong: 18.7,
nodeLat: 47,
nodeLong: 15.4566
},
{
deviceLat: 60.5,
deviceLong: 18.7,
nodeLat: 47,
nodeLong: 15.4566
}]
return (
<MapContainer
style={{ marginLeft: "200px" }}
center={[devices[0].latitude, devices[0].longitude]}
zoom={6}
scrollWheelZoom={true}
bounds={[[90, 180], [-90, 180]]}
minZoom={2}
maxBoundsViscosity={1.0}
>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{arrOfLatLang.length > 0 && arrOfLatLang?.map((point: any) => {
return <Polyline key={point.deviceId} positions={[
[point.nodeLat, point.nodeLong], [point.deviceLat, point.deviceLong]
]} color={'blue'} dashArray="5,10" />
})}
{nodes?.map((point: any) => (
<Marker
zIndexOffset={100}
key={point.Id}
position={[
point.latitude,
point.longitude
]}
>
<Popup>
<br />
Node: {point.name}
<br />
State:
<span className={`text-${point.color}`}>
<b>{point.state}</b>
</span>
</Popup>
</Marker>
))}
{devices?.map((dev: any) => {
return <Marker
key={dev.deviceId}
position={[
dev.latitude,
dev.longitude
]}
>
<Popup>
Device id: {dev.deviceId}
</Popup>
</Marker>
})}
</MapContainer>
)}
您使用了底层传单实例类型。对于地图,其 L.Map
,对于要素组,其 L.FeatureGroup
:
var mapRef = useRef<L.Map>();
var groupRef = useRef<L.FeatureGroup>();
请注意,在 whenCreated
中设置地图参考,就像您在 whenCreated={mapInstance => { mapRef.current = mapInstance }}
中所做的那样,这不是一个好主意,并且可能会导致您尝试输入的方式出现问题参考。我建议在 MapContainer (ref={mapRef}
) 上使用适当的 ref 属性,或者将 mapRef
设置为状态变量,如 example in the react-leaflet docs.
中所述
问题是在我的 React 项目中使用 TS 时,我需要设置 useRef()
函数的类型,但我不知道它是什么。因此,在下面的代码中,我将其设置为 any
,然后调用 leafletElement
。出现的问题是即使在通过 whenCreated
函数 iside MapContainer
.
我试图以一种显示所有 Marker
的方式设置 MapContainer
使其动态调整大小,因此当位置更改时它会更新它并调整 MapContainer
因为它没有 ref
属性.
Example I'm trying to reproduce
const MapTry = () => {
const [nodes, setNodes] = useState<INode[]>([]);
const [devices, setDevices] = useState<IDevice[]>([]);
const [nodeDeviceTest, deviceNodeConnection] = useState([]);
var arrObj: any = [];
var arrOfBounds: any = [];
var mapRef = useRef<any>();
var groupRef = useRef<any>();
var device = new L.Icon({
iconUrl: deviceCar,
iconSize: [30, 30],
iconAnchor: [16, 3],
popupAnchor: [1, -1],
shadowSize: [41, 41]
});
var deviceNode = new L.Icon({
iconUrl: nodeDevice,
iconSize: [20, 30],
iconAnchor: [10, 0],
popupAnchor: [1, -34],
shadowSize: [41, 41],
})
useEffect(() => {
async function fetchData() {
const user = checkUserData();
const project = checkProjectData();
debugger;
if (mapRef.current && mapRef) {
let map = mapRef.current.leafletElement;
let group = groupRef.current.leafletElement;
map.fitBounds(group.getBounds());
}
const result = await getProjectNodeDeviceMap(project, user);
console.log(result);
if (result) {
if (result.devicesToNodes) {
for (var i = 0; i < result.devicesToNodes.length; i++) {
var objec = {
nodeId: "",
devId: "",
deviceLat: 0,
deviceLong: 0,
nodeLat: 0,
nodeLong: 0
}
for (var j = 0; j < result.devices.length; j++) {
if (result.devicesToNodes[i].deviceId == result.devices[j].deviceId) {
objec.deviceLat = result.devices[j].latitude
objec.deviceLong = result.devices[j].longitude
objec.devId = result.devices[j].deviceId
arrOfBounds.push([result.devices[j].latitude, result.devices[j].longitude])
for (var k = 0; k < result.nodes.length; k++) {
if (result.devicesToNodes[i].nodeId == result.nodes[k].id) {
objec.nodeLat = result.nodes[k].latitude
objec.nodeLong = result.nodes[k].longitude
objec.nodeId = result.nodes[k].id
arrOfBounds.push([result.nodes[k].latitude, result.nodes[k].longitude])
arrObj.push(objec);
break;
}
}
}
}
deviceNodeConnection(arrObj);
}
}
if (result.nodes) {
result.nodes.map((node: INode) => {
if (node.state == "running") {
node.color = "success";
}
else if (node.state == "error") {
node.color = "danger";
}
else if (node.state == "stopped") {
node.color = "warning";
}
else {
node.color = "info";
}
})
}
setNodes(result.nodes)
setDevices(result.devices)
}
}
const timer = setInterval(() => {
fetchData();
}, 3000)
return () => clearTimeout(timer);
}, [arrObj])
return (
<div className="col-md-9">
<div className="card shadow p-3 mb-5 bg-white rounded">
<div className="text-center">
<h3>Showcase</h3>
</div>
{devices && devices.length > 0 && <MapContainer
whenCreated={mapInstance => { mapRef.current = mapInstance }}
center={[devices[0].latitude, devices[0].longitude]}
zoom={6}
scrollWheelZoom={true}
minZoom={2}
maxBoundsViscosity={1.0}
zoomControl={false}
style={{ backgroundColor: "inherit", width: "100%", height: "60vh" }}
>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{nodeDeviceTest.length > 0 && nodeDeviceTest?.map((point: any) => {
return <Polyline key={point.deviceId} positions={[
[point.nodeLat, point.nodeLong], [point.deviceLat, point.deviceLong]
]} color={'blue'} dashArray="5,10" />
})}
<FeatureGroup ref={groupRef}>
{nodes?.map((point: any) => (
<Marker
zIndexOffset={100}
icon={deviceNode}
key={point.Id}
position={[
point.latitude,
point.longitude
]}
>
<Popup>
<br />
Node: {point.name}
<br />
State:
<span className={`text-${point.color}`}>
<b>{point.state}</b>
</span>
</Popup>
</Marker>
))}
{devices?.map((dev: any) => {
return <Marker
key={dev.deviceId}
position={[
dev.latitude,
dev.longitude
]}
icon={device}
>
<Popup>
Device id: {dev.deviceId}
</Popup>
</Marker>
})}
</FeatureGroup>
</MapContainer>}
</div>
</div>
)}
此外,如果我在解释中遗漏了什么,我希望 FeatureGroup
是正确的 referenced.Sorry。我是 React/TS.
编辑:这是我创建的示例代码
const Mapp = () => {
const devices = [{
deviceId: "1-528a-4f80-9c7a-124108f86895",
latitude: 45.5,
longitude: 18.7
},
{
deviceId: "2-528a-4f80-9c7a-124108f86895",
latitude: 60.5,
longitude: 18.7
}]
const nodes = [{
id: "test-node-1",
latitude: 45,
longitude: 15.4566,
name: "TestNode1",
state: "running",
},
{
id: "test-node-2",
latitude: 47,
longitude: 15.4566,
name: "TestNode2",
state: "running",
}]
const devicesToNodes = [{
deviceId: "1-528a-4f80-9c7a-124108f86895",
nodeId: "test-node-1"
},
{
deviceId: "2-528a-4f80-9c7a-124108f86895",
nodeId: "test-node-1"
}]
const arrOfLatLang = [{
deviceLat: 45.5,
deviceLong: 18.7,
nodeLat: 47,
nodeLong: 15.4566
},
{
deviceLat: 60.5,
deviceLong: 18.7,
nodeLat: 47,
nodeLong: 15.4566
}]
return (
<MapContainer
style={{ marginLeft: "200px" }}
center={[devices[0].latitude, devices[0].longitude]}
zoom={6}
scrollWheelZoom={true}
bounds={[[90, 180], [-90, 180]]}
minZoom={2}
maxBoundsViscosity={1.0}
>
<TileLayer
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{arrOfLatLang.length > 0 && arrOfLatLang?.map((point: any) => {
return <Polyline key={point.deviceId} positions={[
[point.nodeLat, point.nodeLong], [point.deviceLat, point.deviceLong]
]} color={'blue'} dashArray="5,10" />
})}
{nodes?.map((point: any) => (
<Marker
zIndexOffset={100}
key={point.Id}
position={[
point.latitude,
point.longitude
]}
>
<Popup>
<br />
Node: {point.name}
<br />
State:
<span className={`text-${point.color}`}>
<b>{point.state}</b>
</span>
</Popup>
</Marker>
))}
{devices?.map((dev: any) => {
return <Marker
key={dev.deviceId}
position={[
dev.latitude,
dev.longitude
]}
>
<Popup>
Device id: {dev.deviceId}
</Popup>
</Marker>
})}
</MapContainer>
)}
您使用了底层传单实例类型。对于地图,其 L.Map
,对于要素组,其 L.FeatureGroup
:
var mapRef = useRef<L.Map>();
var groupRef = useRef<L.FeatureGroup>();
请注意,在 whenCreated
中设置地图参考,就像您在 whenCreated={mapInstance => { mapRef.current = mapInstance }}
中所做的那样,这不是一个好主意,并且可能会导致您尝试输入的方式出现问题参考。我建议在 MapContainer (ref={mapRef}
) 上使用适当的 ref 属性,或者将 mapRef
设置为状态变量,如 example in the react-leaflet docs.