我是React新手,所以也许问一个愚蠢的问题,但这使我感到困惑。作为学习的一部分,我将构建一个包含三个部分的应用程序-父级About
和两个子级[GoogleMap
和MapMarkerDetails
)。父级进行数据协调,一个孩子显示带有两个标记的google map作为默认地图,另一个孩子在单击时显示标记的详细信息。
现在,我添加了单击地图时添加新标记的功能。大多数功能均可正常工作-绘制地图,添加默认标记,然后单击其中一个标记,这会在父类上调用一个函数,该函数会更新其状态并将其传播到MapMarkerDetails
元素和显示简单消息。
这里是我评论过的以帮助理解的父类:
import React, { Component } from 'react';
import GoogleMap from './GoogleMap'
import MapMarkerDetails from './MapMarkerDetails'
class About extends Component {
state = {
markers: [{
position: { lat: 51.438759, lng: -2.864514 },
label: 'A',
map: null,
}, {
position: { lat: 51.433636, lng: -2.868734 },
label: 'B',
map: null,
}],
greeting: 'HelloA'
}
showMarkerInfo = (label) => {
this.setState({greeting: ('Hello ' + label)})
}
/*
Adding a new Marker
This function is called from the child element GoogleMap
However, the setState(...) dosn't seem to propogate down to the GoogleMap element.
*/
addMarker = (latlng) => {
let newMarker = [{
position: { lat: latlng.lat(), lng: latlng.lng() },
label: 'New',
map: null,
}];
/* Creates a new array for updating state. Is this the best way to do this */
let markers = [...this.state.markers, ...newMarker]
this.setState({markers});
console.log(this.state) // This shows the added marker
}
render() {
return (
<div className="container">
<h4 className="center">About</h4>
<MapMarkerDetails details={this.state.greeting}/>
<GoogleMap markers={this.state.markers} clickedMarker={this.showMarkerInfo} addMarker={this.addMarker}/>
</div>
)
}
}
export default About;
这里是显示Google Map和标记的类:
import React, { Component } from 'react';
class GoogleMap extends Component {
constructor(props) {
super(props);
this.googleMapRef = React.createRef(); // Create a referance for Google Map to draw to
console.log('Constructore')
}
componentDidMount(){
console.log('componentDidMount')
/* Create the Map */
let googleMap = new window.google.maps.Map(this.googleMapRef.current, {
zoom: 15,
center: {
lat: 51.436411,
lng: -2.861980,
},
disableDefaultUI: true,
})
this.placeMMarkers(googleMap) // Place the markers
this.addMapListner(googleMap) // Define a click listener to place new markers
}
/* Place the markers */
placeMMarkers = (googleMap) => {
this.props.markers.forEach((m) => {
m.map = googleMap;
let marker= new window.google.maps.Marker(m)
marker.addListener('click', () => { this.props.clickedMarker(m.label); });
}
);
}
/* Map listeners */
addMapListner = (googleMap) => {
googleMap.addListener('click', (e) => {
this.props.addMarker(e.latLng)
})
}
render() {
console.log('render: ' + this.props.markers) // This is showing the added markers
return (
<div
id="google-map"
ref={this.googleMapRef}
style={{ width: '800px', height: '400px', float: 'left' }}>
</div>
)
}
}
export default GoogleMap
我已将控制台日志记录添加到每个功能,因此我可以跟踪发生的情况。
这里是MapMarkerDetails
,当单击标记时,它会显示一条简单消息。这一切都很好。
import React, { Component } from 'react';
class MapMarkerDetails extends Component {
render(){
return (
<div style={{width: '100px', height: '400px', backgroundColor: 'gray', float: 'left'}}>
{this.props.details}
</div>
)
}
}
export default MapMarkerDetails
问题描述
[当用户单击地图(而不是标记)时,它将调用从父addMarker
类(下面的代码段)向下传递的函数About
。在addMarker
的About
功能中,输入经纬度。这表示用户单击的位置。将其转换为marker
数据对象,然后创建一个新数组,其中包含默认标记和新标记。我不确定我的新数组创建是否以最佳方式完成-如果没有让我知道。
一旦创建了新数组,我们将使用this.setState({markers})
更新组件状态。我认为这将导致重新render()
并使用添加的标记重新绘制地图。但不是。
addMarker = (latlng) => {
let newMarker = [{
position: { lat: latlng.lat(), lng: latlng.lng() },
label: 'New',
map: null,
}];
/* Creates a new array for updating state. Is this the best way to do this */
let markers = [...this.state.markers, ...newMarker]
this.setState({markers});
console.log(this.state) // This shows the added marker
}
发生某种情况,导致调用了render()
的GoogleMap
函数,但是只显示了原始标记。数据向下传递到GoogleMap
组件,因为我可以看到console.log('render: ' + this.props.markers)
的输出。但是如何获取所有标记?
[请告知About
将数据传递到GoogleMap
以便可以添加新标记的最佳方法是什么。
就像在首次加载地图时使用componentDidMount
强制添加标记一样,在更改道具时,也应使用componentDidUpdate
做相同的事情。在您的GoogleMap组件中:
componentDidUpdate() {
this.placeMMarkers(googleMap) // Place the markers
}
由于在placeMMarkers
中附加了事件处理程序,因此还应该添加一些逻辑以区分新标记和现有标记,以避免将多个事件处理程序添加到现有标记。