无法读取未定义的 属性 '#<Object>' ,在检索 onClick Custom React 之后
Cannot read property '#<Object>' of undefined , after retriving onClick Custom React
我正在制作一张带有 dipslay 标记的传单地图。这些标记除了纬度和经度之外还有其他数据,(在这种情况下是键)
我正在使用 react-leaflet 存储库中的自定义 React 组件。我可以获得多个标记位置,但是当我尝试检索我单击的标记并将其传递给子组件时,我得到
无法读取未定义的属性“# < Object >”
我可以传递所有数据,但没有问题。
当我尝试将 "clicked" 标记传递给 Card 和 Cartitle 组件时出现此错误。
到目前为止我尝试过的:
在我做的 handleToggle 函数中:
index = this.props.places[index]
但那是我收到上述错误的时候。我做错了什么?
P.D。此外,我能够显示 ALL 子组件的数据
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
方法是 Marker
组件的 onClick
处理程序。 React 中的 onClick
处理程序默认传递一个合成事件对象(有关此 here 的更多信息)。
因此传递给 handleToggle
方法的 index
将是合成事件对象,它不会帮助您从 places
数组中获取标记的索引。您必须将索引显式传递到 handleToggle
方法中。为此,您需要进行以下更改:
1> 将构造函数中函数的绑定修改为:
this.handleToggle = this.handleToggle.bind(this,index);
2> 在 MyPopupMarker
组件中显式传递索引:
const MyPopupMarker = ({ children, position,index }) => (
<Marker
onClick={()=>this.handleToggle(index)}
....
)
3> 在MarkerList
组件
中将索引传递给MyPopupMarker
组件
const items = markers.map(({ key, ...props },i) => (
<MyPopupMarker key={key} index={i} {...props}/>
))
4> 从 state
对象而不是 props
对象中的 places
数组访问索引。
handleToggle(index) {
const self = this;
self.setState({
open: !this.state.open,
places: markers
});
var selectedMarker = this.state.places[index];
console.log(this.state.places)
}
错误消息 无法读取 属性 '# < Object > ' of undefined 的原因是您试图访问 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
函数作为 props 并将其与 index
一起传递给 MyPopupMarker
组件
const MarkerList = ({ markers, handleToggle }) => {
const items = markers.map(({ key, ...props }, i) => (
<MyPopupMarker key={key} {...props} index={i} handleToggle={handleToggle} />
));
return <div >{items}</div>;
};
Mapper 组件:该组件将 handleToggle
函数与 markers
一起传递给 MarkerList
组件
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;
找到完整的工作示例
我正在制作一张带有 dipslay 标记的传单地图。这些标记除了纬度和经度之外还有其他数据,(在这种情况下是键)
我正在使用 react-leaflet 存储库中的自定义 React 组件。我可以获得多个标记位置,但是当我尝试检索我单击的标记并将其传递给子组件时,我得到
无法读取未定义的属性“# < Object >”
我可以传递所有数据,但没有问题。
当我尝试将 "clicked" 标记传递给 Card 和 Cartitle 组件时出现此错误。
到目前为止我尝试过的:
在我做的 handleToggle 函数中:
index = this.props.places[index]
但那是我收到上述错误的时候。我做错了什么?
P.D。此外,我能够显示 ALL 子组件的数据
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
方法是 Marker
组件的 onClick
处理程序。 React 中的 onClick
处理程序默认传递一个合成事件对象(有关此 here 的更多信息)。
因此传递给 handleToggle
方法的 index
将是合成事件对象,它不会帮助您从 places
数组中获取标记的索引。您必须将索引显式传递到 handleToggle
方法中。为此,您需要进行以下更改:
1> 将构造函数中函数的绑定修改为:
this.handleToggle = this.handleToggle.bind(this,index);
2> 在 MyPopupMarker
组件中显式传递索引:
const MyPopupMarker = ({ children, position,index }) => (
<Marker
onClick={()=>this.handleToggle(index)}
....
)
3> 在MarkerList
组件
MyPopupMarker
组件
const items = markers.map(({ key, ...props },i) => (
<MyPopupMarker key={key} index={i} {...props}/>
))
4> 从 state
对象而不是 props
对象中的 places
数组访问索引。
handleToggle(index) {
const self = this;
self.setState({
open: !this.state.open,
places: markers
});
var selectedMarker = this.state.places[index];
console.log(this.state.places)
}
错误消息 无法读取 属性 '# < Object > ' of undefined 的原因是您试图访问 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
函数作为 props 并将其与 index
MyPopupMarker
组件
const MarkerList = ({ markers, handleToggle }) => {
const items = markers.map(({ key, ...props }, i) => (
<MyPopupMarker key={key} {...props} index={i} handleToggle={handleToggle} />
));
return <div >{items}</div>;
};
Mapper 组件:该组件将 handleToggle
函数与 markers
MarkerList
组件
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;
找到完整的工作示例