无法读取属性&#39;#<object>&#39;未完成,在重新启动onClick Custom React之后

时间:2017-11-05 16:56:19

标签: javascript reactjs leaflet react-leaflet

我正在构建一个传单标记的传单地图。这些标记除了lat和long之外还有其他数据(在这种情况下为键)

我正在使用react-leaflet repo中的自定义反应组件。我可以获得多个标记位置,但是当我尝试检索我点击的标记并将其传递给子组件时我得到了

无法读取属性&#39;#&lt;对象&gt; &#39;未定义的

我可以传递所有数据,但没有问题。

当我尝试将&#34;点击的&#34; 标记传递给Card和Cartitle组件时,我收到此错误。

到目前为止我已尝试过:

在handleToggle函数中,我做了:

index = this.props.places [index]

但是当我得到上面的错误时。我做错了什么?

Pd积。此外,我能够将 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;

1 个答案:

答案 0 :(得分:1)

您的handleToggle方法是onClick组件的Marker处理程序。 React中的onClick处理程序默认传递一个合成事件对象(有关此here的更多信息)。

因此传递给index方法的handleToggle将是合成事件对象,这无法帮助您从places数组中获取标记的索引。您必须将索引显式传递到handleToggle方法中。为此,您需要进行以下更改:

1&GT;将构造函数中函数的绑定更改为:

this.handleToggle = this.handleToggle.bind(this,index);

2 - ;在MyPopupMarker组件中明确传递索引:

const MyPopupMarker = ({ children, position,index }) => (
<Marker
        onClick={()=>this.handleToggle(index)}
 ....
 )

3&GT;将索引传递给MyPopupMarker组件

中的MarkerList组件
 const items = markers.map(({ key, ...props },i) => (
    <MyPopupMarker key={key}  index={i} {...props}/>
  ))

4&GT;从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)
  }

错误消息的原因无法读取属性'#&lt;对象&gt; “未定义是您尝试访问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>;
};

Mapper组件:此组件将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

找到完整的工作示例