我正在构建一个包含标记的单张地图。除了纬度和经度,这些标记还具有其他数据(在这种情况下为键)
我正在使用react-leaflet回购中的自定义react组件。我可以获得多个标记位置,但是当我尝试检索标记时,我单击并将其传递给子组件,
无法读取未定义的属性“#”
我可以传递所有数据,尽管没有问题。
当我尝试将“ clicked”标记传递给Card和Cartitle组件时,出现此错误。
到目前为止,我已经尝试过:
在handleToggle函数中,我做了:
索引= this.props.places [索引]
但是那是当我得到上面的错误。我究竟做错了什么?
P.D.而且,我无法将所有数据显示给子组件
import ...
const markers = [
{
key: 'P12345678',
position: [37.786464, -122.411047],
children: 'My first popup'
},
{
key: 'M12345678',
position: [40.689192, -74.044563],
children: 'My second popup'
},
];
class Mapper extends Component {
constructor(props) {
super(props);
this.handleToggle = this.handleToggle.bind(this);
this.handleClose = this.handleClose.bind(this);
this.state = {
lat: 29.761993,
lng: -95.366302,
zoom: 4,
open: false,
places: []
}
}
handleToggle(index) {
const self = this;
self.setState({
open: !this.state.open,
places: markers
});
// index = this.props.places[index]
console.log(this.state.places)
}
handleClose() {
this.setState({
open: false
});
}
render() {
const center = [this.state.lat, this.state.lng];
//Custom Marker Component
const MyPopupMarker = ({ children, position }) => (
<Marker
onClick={this.handleToggle}
position={position}
places={this.state.places}
>
<Popup>
<span>{children}</span>
</Popup>
</Marker>
)
MyPopupMarker.propTypes = {
// children: MapPropTypes.func,
// position: MapPropTypes.latlng,
}
//Custom Marker List Component
const MarkerList = ({ markers }) => {
const items = markers.map(({ key, ...props }) => (
<MyPopupMarker key={key} {...props} />
))
return <div style={{display: 'none'}}>{items}</div>
}
MarkerList.propTypes = {
markers: MapPropTypes.array.isRequired,
}
// console.log('markers', markers)
return (
<div>
<Map
center={center}
zoom={this.state.zoom}
style={styles.map}>
<TileLayer
url='https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png'
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
/>
<MarkerList markers={markers} />
</Map>
<Drawer
width={500}
openSecondary={true}
docked={false}
open={this.state.open}
onRequestChange={(open) => this.setState({open})}
containerStyle={styles.whitebox}
>
{
markers.map((cf, k) => (
<Card
style={styles.appMedia}
key={k}
>
<CardTitle
titleStyle={styles.drawTitle}
subtitleStyle={styles.drawTitle}
title={cf.key}
subtitle="Common Field Equipment"/>
</Card>
))
}
</Drawer>
</div>
);
}
}
export default Mapper;
最佳答案
您的handleToggle
方法是onClick
组件的Marker
处理程序。默认情况下,React中的onClick
处理函数传递一个合成事件对象(有关此here的更多信息)。
因此,传递给index
方法的handleToggle
将是该合成事件对象,这不会帮助您从places
数组获取标记的索引。您必须将索引显式传递到您的handleToggle
方法中。为此,您需要进行以下更改:
1>将构造函数中的函数绑定更改为:
this.handleToggle = this.handleToggle.bind(this,index);
2>在
MyPopupMarker
组件中显式传递索引:const MyPopupMarker = ({ children, position,index }) => (
<Marker
onClick={()=>this.handleToggle(index)}
....
)
3>将索引传递到
MyPopupMarker
组件中的MarkerList
组件 const items = markers.map(({ key, ...props },i) => (
<MyPopupMarker key={key} index={i} {...props}/>
))
4>从
places
对象而不是state
对象中的props
数组访问索引。handleToggle(index) {
const self = this;
self.setState({
open: !this.state.open,
places: markers
});
var selectedMarker = this.state.places[index];
console.log(this.state.places)
}
错误消息无法读取未定义属性'#'的原因是,您试图访问
places
对象中props
所在的undefined
数组。顺便说一句,我想指出的是,在
render
方法内部创建组件(组件MyPopupMarker
和MarkerList
)不是一个好习惯,因为这些组件会在每个渲染器上创建,这很浪费。如果在Mapper
组件之外声明它们,则效率会更高。编辑:
要将组件移出
render
,您需要以handleToggle
的形式传递props
函数。我将您的代码更改如下:MyPopupMarker组件:该组件将
index
和handleToggle
函数用作道具。const MyPopupMarker = ({ children, position, index, handleToggle }) => (
<Marker onClick={() => handleToggle(index)} position={position}>
<Popup>
<span>{children}</span>
</Popup>
</Marker>
);
MarkerList组件:该组件获取
handleToggle
函数作为道具,并将其与MyPopupMarker
一起传递给index
组件。const MarkerList = ({ markers, handleToggle }) => {
const items = markers.map(({ key, ...props }, i) => (
<MyPopupMarker key={key} {...props} index={i} handleToggle={handleToggle} />
));
return <div >{items}</div>;
};
映射器组件:此组件将
handleToggle
函数与MarkerList
一起传递给markers
组件class Mapper extends Component {
constructor(props) {
super(props);
this.handleToggle = this.handleToggle.bind(this);
this.handleClose = this.handleClose.bind(this);
this.state = {
lat: 29.761993,
lng: -95.366302,
zoom: 4,
open: false,
places: []
};
}
handleToggle(index) {
const self = this;
self.setState({
open: !this.state.open,
places: markers
});
// index = this.props.places[index]
let selectedMarker = this.state.places[index];
console.log(selectedMarker);
}
handleClose() {
this.setState({
open: false
});
}
render() {
const center = [this.state.lat, this.state.lng];
let selectedMarker = this.state.places;
return (
<div>
<Map center={center} zoom={this.state.zoom} style={styles.map}>
<TileLayer
url="https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png"
attribution="© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
/>
<MarkerList markers={markers} handleToggle={this.handleToggle} />
</Map>
<Drawer
width={500}
openSecondary={true}
docked={false}
open={this.state.open}
onRequestChange={open => this.setState({ open })}
containerStyle={styles.whitebox}
>
{selectedMarker.map((value, index) => (
<Card style={styles.appMedia} key={index}>
<CardTitle
titleStyle={styles.drawTitle}
subtitleStyle={styles.drawTitle}
title={value.key}
subtitle="Common Field Equipment"
/>
</Card>
))}
</Drawer>
</div>
);
}
}
export default Mapper;
完整的工作示例可以在https://codesandbox.io/s/4r1yo07kw9中找到