2017-10-20 2 views
0

내지도에있는 각 마커에 대한 정보 창을 만들어야합니다. 지도에서 마커를 볼 수는 있지만 마커를 클릭하여 InfoWindow를 가져 오면이 오류가 TypeError: Cannot read property 'isOpen' of undefined이며 의 this.setState({isOpen: !this.state.isOpen})을 참조합니다. 대신react-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

나는 그것을 작동시키지 못했다 ... 나는'isOpen'을 'marker.key}','{marker.key}}}'list.restaurants.push ({..., isOpen : false})'그리고 나중에'{marker.isOpen &&

관련 문제