2017-10-20 87 views
0

我需要爲我的地圖中的每個標記創建一個信息窗口。我可以在地圖上看到標記,但當我點擊標記以獲取InfoWindow時,出現TypeError: Cannot read property 'isOpen' of undefined錯誤,參考this.setState({isOpen: !this.state.isOpen})中的onToggleOpenreact-google-maps多個標記和信息窗口

感謝代表

componentWillMount() { 
    this.setState({ markers: [], isOpen: false }) 
    } 

componentDidMount() { 
    let list = { restaurants : []} 
    database.ref('..').on('value', .. => { 
      ... 
      }) 
      this.setState({ markers: list.restaurants}); 
     }) 

} 

onToggleOpen(){ 
    this.setState({isOpen: !this.state.isOpen}) 
} 


render() { 
    const MapWithAMarker = compose(
    withProps({ 
     googleMapURL: ..., 
     loadingElement: ..., 
     containerElement: ..., 
     mapElement: ... 
     }), 
     withScriptjs, 
     withGoogleMap 
    )(props => 
     <GoogleMap 
     defaultZoom={17} 
     defaultCenter={{ lat: ..., lng: ... }} 
     > 
      {props.markers.map(marker => (
      <Marker 
       key={marker.name} 
       position={{ lat: marker.latitude, lng: marker.longitude }} 
       onClick={this.onToggleOpen} 
      > 
      {this.state.isOpen && <InfoWindow onCloseClick={this.onToggleOpen}> marker.key </InfoWindow>} 
      </Marker> 
     ))} 


     </GoogleMap> 
    ); 
    return (
     <section id="mapa"> 
      <div class= "container"> 
       <div class="row"> 
        <div class="col-md-12 text-left"> 
         <h2 class="section-heading">MAPA</h2> 

         <MapWithAMarker markers={this.state.markers}/> 

        </div> 
       </div> 
       <div class="row text-center"> 

       </div> 
      </div> 
     </section> 
    ) 
} 

編輯:更新後的代碼:

export default class Mapa extends Component { 
    constructor(props) { 
    super(props) 
    this.state = { 
     markers: [], 
     isOpen: false 
    } 
    } 

componentDidMount() { 
    let list = { restaurants : []} 
    database.ref('..').on('value', restaurants => { 
      restaurants.forEach(restaurant => { 
        list.restaurants.push({'name': restaurant.key, 
          'longitude': restaurant.val().lng, 
          'latitude': restaurant.val().lat} 

         ) 
      }) 
      this.setState({ markers: list.restaurants }); 
     }) 

} 

onToggleOpen =() => { 
     this.setState({isOpen: !this.state.isOpen}) 
    } 

render() { 

    const MapWithAMarker = compose(
    withProps({ 
     googleMapURL: "https://maps.googleapis.com/maps/api/js?key=...&v=3.exp&libraries=geometry,drawing,places", 
     loadingElement: <div style={{ height: `100%` }} />, 
     containerElement: <div style={{ height: `400px` }} />, 
     mapElement: <div style={{ height: `100%` }} /> 
     }), 
     withScriptjs, 
     withGoogleMap 
    )(props => 
     <GoogleMap 
     defaultZoom={17} 
     defaultCenter={{ lat: .., lng: ... }} 
     > 
      {props.markers.map(marker => (
      <Marker 
       key={marker.name} 
       position={{ lat: marker.latitude, lng: marker.longitude }} 
       onClick={this.onToggleOpen} 
      > 
      {this.state.isOpen && <InfoWindow onCloseClick={this.onToggleOpen}> marker.key </InfoWindow>} 
      </Marker> 
     ))} 

     </GoogleMap> 
    ); 
    return (
     <section id="mapa"> 
      <div class= "container"> 
      <h3 class="info-title"><span class="info-title-span">Tasty and Convenient.</span></h3> 
       <div class="row"> 
        <div class="col-md-12 text-left"> 


         <MapWithAMarker markers={this.state.markers}/> 

        </div> 
       </div> 
       <div class="row text-center"> 

       </div> 
      </div> 
     </section> 
    ) 
} 
+0

就本聲明的渲染方法,所以它的範圍從那裏調用它:'VAR ISOPEN = this.state.isOpen;' – fungusanthrax

回答

3

錯誤表明,你在哪裏試圖檢索this.state.isOpen範圍內this.state == undefined

這是因爲您的this.onToggleOpen()函數的作用域未正確綁定到您的組件。

嘗試重構它使用箭頭功能,像這樣:

onToggleOpen =() => { 
    this.setState({isOpen: !this.state.isOpen}) 
} 

旁註:

最佳實踐聲明初始this.state是您的組件的constructor生命週期方法中這樣做,像這樣:

constructor(props) { 
    super(props) 
    this.state = { 
    markers: [], 
    isOpen: false 
    } 
} 

另外,應該this.state.isOpen對於您的每個markers而言都是獨一無二的財產,而不是全部的價值?這樣您就可以單獨打開每個標記,而不是一次打開所有標記。

解決方案示例:

// React. 
import React from 'react' 


// Other Dependencies... 


// <Map/>. 
export default class Map extends React.Component { 

    // Constructor. 
    constructor(props) { 

    // Super Props. 
    super(props) 

    // State. 
    this.state = { 
     markers: [] 
    } 
    } 


    // Render. 
    render() { 

    // Map With A Marker. 
    const MapWithAMarker = compose(
     withProps({ 
     googleMapURL: "https://maps.googleapis.com/maps/api/js?key=...&v=3.exp&libraries=geometry,drawing,places", 
     loadingElement: <div style={{ height: `100%` }} />, 
     containerElement: <div style={{ height: `400px` }} />, 
     mapElement: <div style={{ height: `100%` }} /> 
     }), 
     withScriptjs, 
     withGoogleMap 
    )(props => 
     <GoogleMap defaultZoom={17} defaultCenter={{ lat: .., lng: ... }}> 
      {props.markers.map(props => (
      <RestaurantMarker key={props.name} {...props}/> 
     ))} 
     </GoogleMap> 
    ) 

    // Return Map. 
    return (
     <section id="mapa"> 
      <div class= "container"> 
      <h3 class="info-title"><span class="info-title-span">Tasty and Convenient.</span></h3> 
      <div class="row"> 
       <div class="col-md-12 text-left"> 
       <MapWithAMarker markers={this.state.markers}/> 
       </div> 
      </div> 
      <div class="row text-center"> 

      </div> 
      </div> 
     </section> 
    ) 
    } 

    // Did Mount. 
    componentDidMount() { 

    // Download Restaurants. 
    database.ref('..').on('value', restaurants => { 

     // Restaurants Placeholder. 
     let restaurants : [] 

     // Map Restaurants To List. 
     restaurants.forEach((restaurant) => { 
     restaurants.push({ 
      'name': restaurant.key, 
      'longitude': restaurant.val().lng, 
      'latitude': restaurant.val().lat 
     }) 
     }) 

     // Update State. 
     this.setState({ 
     markers: restaurants 
     }) 
    }) 
    } 
} 


// <RestaurantMarker/>. 
class RestaurantMarker extends React.Component { 

    // Constructor. 
    constructor(props) { 

    // Super Props. 
    super(props) 

    // State. 
    this.state = { 
     open: false 
    } 
    } 

    // Render. 
    render() { 


    // Extract Props. 
    const { 
     props: { 
     name, 
     latitude, 
     longitude 
     } 
    } = this 


    // Return Restaurant Marker Component. 
    return (
     <Marker key={name} position={{ lat: latitude, lng: longitude }}> 
     {this.state.open ? (
      <InfoWindow onClick={() => this.setState({open: !this.state.open})}> {name} </InfoWindow> 
     ) : ''} 
     </Marker> 
    ) 
    } 
} 
+0

我怎麼會爲每個屬性的標記?當然,我只是想點擊標記的信息窗口..也許通過道具傳遞'isOpen'? –

+0

我會插入邏輯來檢查呈現時每個'this.state.markers'子項的'isOpen'屬性。即。在你的'props.markers.map()'函數中:'if(marker.isOpen){//返回打開版本的標記}' –

+0

我不能使它工作......我試圖在'list.restaurants.push({...,isOpen:false})'和稍後{'marker.isOpen && marker.key}',但是我不知道該怎麼做'onToggleOpen'功能,所以我可以改變道具... –