React ref.current在componentDidUpdate中仍然为null



我正试图使用react map gl放大一组坐标。为此,图书馆鼓励我们使用React的参考文献。在render中实例化组件时,我传递一个ref,该ref应该包含底层MapBox映射对象。我设法使行为正常。唯一的问题是:它高度不一致。

我在componentDidUpdate中调用一个名为setCamera的方法。但它只适用于初始负载。如果我重新加载页面,我会从盖茨比那里得到一个错误。如果我关闭错误,它将再次工作。直到下一次重新加载。

错误是this.mapRef.currentnull。在尝试访问之前,我试图设置一个条件来验证该值不是null,但这会导致动画永远无法工作。无论我重新加载多少次,都不会执行。然而,如果没有条件,它至少可以在崩溃前工作一半的时间。所以这本身就是个谜,如果有人知道为什么会发生这种行为,我会洗耳恭听。

尽管如此,我并没有气馁,并试图将对setCamera的调用放在setTimeout中,是的,它很有效!即使像1这样设置很低的超时,代码也能在95%的时间内工作。但我对此并不满意,因为我明白,放置这种计时器不是我应该做的,更糟糕的是,它并不能始终如一地解决问题。

我对这个问题的理解是,由于某种原因,MapRef仍然没有在componentDidUpdate中设置。它有时会晚些时候设置。我不知道React是否支持线程,或者某种异步魔法是否在幕后欺骗了我,但我想知道的是我什么时候能保证我的ref设置正确我应该在哪里或如何编写此代码

提前感谢任何能在这方面帮助我的人。🙂

这是我的示例代码:

import React, {Component} from 'react';
import MapGL, {NavigationControl, Source, Layer} from 'react-map-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
import gpxParser from 'gpxparser';
import bbox from '@turf/bbox';
const MAPBOX_TOKEN = 'exampleToken'
class HikeMapbox extends Component {
constructor(props) {
super(props)
this.state = {
gpxData: '',
};
}
// Read et get the GPX file, return it as a bunch of text
componentDidMount() {
const gpxPath = `https:${this.props.gpxPath}`;
// Simple GET request using fetch
fetch(gpxPath)
.then(response => response.text())
.then(text => this.setState({ gpxData: text }));
}
componentDidUpdate() {
// Set the camera on didUpdate
setTimeout(() => {
const geoJsonData = this.getGeoJson();
this.setCamera(geoJsonData);
}, 10);
}
// Get Max and Min Lat and Lon to Zoom on the GPX trace
setCamera(geoJsonData) {
if (geoJsonData) {
const [minLng, minLat, maxLng, maxLat] = bbox(geoJsonData);
this.mapRef.current.fitBounds(
[
[minLng, minLat],
[maxLng, maxLat]
],
{padding: 40}
);
}
}
// Take the text and parse it as geoJSON
getGeoJson() {
const { gpxData } = this.state;
let gpx = new gpxParser();

try {
gpx.parse(gpxData);
} catch (err) {
console.log(err);
}
const geoJson = gpx.toGeoJSON();   
return geoJson
}
// Return the GPX trace in Mapbox
showGpxFile() {
const GeoJsonData = this.getGeoJson();
// Choose the style of the GPX trace
const layerStyle = {
id:'contours',
type:'line',
source:'contours',
paint: {
'line-color': 'blue',
'line-width': 3
}
};
return (
<>
{
// Return the React Mapbox GL code to show the GPX file on the map
GeoJsonData && (
<Source type="geojson" data={GeoJsonData}>
<Layer {...layerStyle} />
</Source>
)
}
</>
)
}

render() {
this.mapRef = React.createRef();
return (
<>
<MapGL
ref={this.mapRef}
initialViewState={{
latitude: this.props.latitude,
longitude: this.props.longitude,
zoom: 8,
}}
style={{width: "100%", height: "100%"}}
mapStyle="mapbox://styles/mapbox/outdoors-v11"
mapboxAccessToken={MAPBOX_TOKEN}
>
<NavigationControl />
{this.showGpxFile()}
</MapGL>
</>
)
}

}
export default HikeMapbox;

顺便说一下,我正在用gatsby develop在我的电脑上运行这段代码。我不知道这是否有关联,但我认为这可能有关联。

我找到了一个解决方案!

我的问题是setCamera依赖于两个条件,这两个条件可以以任何顺序发生。

  1. 获取成功,我们有数据要显示
  2. 地图已加载,我们有它的参考

我没有在构造函数或render中初始化mapRef,而是制作了一个函数…

onMapRefChange = node => {
this.setState({mapRef: node});
// I'm calling my method now
this.setCamera()
};

…我正在传递参考参数

<MapGL
ref={this.onMapRefChange}
...

最终onMapRefChange将接收到一个实际的地图对象,然后setCamera中的代码将能够访问它

最新更新