无法读取未定义的 属性 '#<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='&copy; <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 方法中创建组件(组件 MyPopupMarkerMarkerList)不是一个好的做法,因为这些组件会在每个渲染器上创建,这会很浪费。如果您在 Mapper 组件之外声明它们,效率会高得多。 编辑:

要将组件移出 render,您需要将 handleToggle 函数作为 props 传入。我已将您的代码更改如下:

MyPopupMarker 组件:此组件获取 indexhandleToggle 函数作为属性。

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="&copy; <a href=&quot;http://osm.org/copyright&quot;>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

找到完整的工作示例