我正在构建一个包含标记的单张地图。除了纬度和经度,这些标记还具有其他数据(在这种情况下为键)

我正在使用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='&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方法是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方法内部创建组件(组件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函数作为道具,并将其与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="&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中找到

07-24 20:31