2017-08-09 5 views
0

私は、ページがロードされる前にレンダリングされているということを知っています。react-google-mapsを使用していて、ユーザーの場所からマーカーを作成しようとしています。問題は、状態がreduxからロードされるまで、状態が空の配列であることです。どのようにこの問題に対処するのですか?私は以下のコードを投稿します。この気レンダリングの前に状態をロードする方法は?

機能がgenerateInitialMarkers()あり、それはmarkersthis.stateconstructor()方法でそれに渡されたアイテムを取得しています。コンポーネントは、希望のブラウザを受信すると

/* global google */ 
import { default as React, Component } from 'react'; 
import raf from 'raf'; 
import canUseDOM from 'can-use-dom'; 
import { connect } from 'react-redux'; 
import { withGoogleMap, GoogleMap, Circle, InfoWindow, Marker } from 'react-google-maps'; 
import withScriptjs from 'react-google-maps/lib/async/withScriptjs'; 

const googleMapURL = 
    'https://maps.googleapis.com/maps/api/js?v=3.27&libraries=places,geometry&key=AIzaSyA7XEFRxE4Lm28tAh44M_568fCLOP_On3k'; 
const geolocation = 
    canUseDOM && navigator.geolocation 
    ? navigator.geolocation 
    : { 
     getCurrentPosition(success, failure) { 
     failure("Your browser doesn't support geolocation."); 
     }, 
    }; 
const GeolocationExampleGoogleMap = withScriptjs(
    withGoogleMap(props => 
    <GoogleMap defaultZoom={8} center={props.center}> 
     {props.center && 
     <InfoWindow position={props.center}> 
      <div>User's Location</div> 
     </InfoWindow>} 
     {props.center && 
     <Circle 
      center={props.center} 
      radius={props.radius} 
      options={{ 
      fillColor: 'red', 
      fillOpacity: 0.2, 
      strokeColor: 'red', 
      strokeOpacity: 1, 
      strokeWeight: 1, 
      }} 
     />} 
     > 
     {props.markers.map((marker, index) => { 
     const onClick =() => props.onMarkerClick(marker); 
     const onCloseClick =() => props.onCloseClick(marker); 

     return (
      <Marker 
      key={index} 
      position={marker.position} 
      title={(index + 1).toString()} 
      onClick={onClick} 
      > 
      {marker.showInfo && 
       <InfoWindow onCloseClick={onCloseClick}> 
       <div> 
        <strong> 
        <h2> 
         {marker.content} 
        </h2> 
        </strong> 
        <br /> 
        <h3>Where we can add offer details!</h3> 
       </div> 
       </InfoWindow>} 
      </Marker> 
     ); 
     })} 
    </GoogleMap>, 
), 
); 

function generateInitialMarkers(items) { 
    console.log('item', items); 
    const markers = []; 
    items.map((item, i) => { 
    const newGeoArr = item.geolocation.split(','); 
    item.position = { lat: newGeoArr[0], lng: newGeoArr[1] }; 
    markers.push({ 
     position: item.position, 
     content: item.description, 
     showInfo: false, 
    }); 
    }); 

    console.log('markers: ', markers); 
    return markers; 
} 

class OfferMap extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     center: null, 
     content: null, 
     radius: 100000, 
     markers: generateInitialMarkers(this.props.browser.items), 
    }; 

    const isUnmounted = false; 

    this.handleMarkerClick = this.handleMarkerClick.bind(this); 
    this.handleCloseClick = this.handleCloseClick.bind(this); 
    } 

    handleMarkerClick(targetMarker) { 
    this.setState({ 
     markers: this.state.markers.map((marker) => { 
     if (marker === targetMarker) { 
      return { 
      ...marker, 
      showInfo: true, 
      }; 
     } 
     return marker; 
     }), 
    }); 
    } 

    handleCloseClick(targetMarker) { 
    this.setState({ 
     markers: this.state.markers.map((marker) => { 
     if (marker === targetMarker) { 
      return { 
      ...marker, 
      showInfo: false, 
      }; 
     } 
     return marker; 
     }), 
    }); 
    } 

    componentDidMount() { 
    const tick =() => { 
     if (this.isUnmounted) { 
     return; 
     } 
     this.setState({ radius: Math.max(this.state.radius - 200, 0) }); 

     if (this.state.radius > 100) { 
     raf(tick); 
     } 
    }; 

    geolocation.getCurrentPosition(
     (position) => { 
     if (this.isUnmounted) { 
      return; 
     } 
     this.setState({ 
      center: { 
      lat: position.coords.latitude, 
      lng: position.coords.longitude, 
      }, 
      content: 'Location found using HTML5.', 
     }); 

     raf(tick); 
     }, 
     (reason) => { 
     if (this.isUnmounted) { 
      return; 
     } 

     this.setState({ 
      center: { 
      lat: 60, 
      lng: 105, 
      }, 
      content: `Error: The Geolocation service failed (${reason}).`, 
     }); 
     }, 
    ); 
    } 

    componentWillUnmount() { 
    this.isUnmounted = true; 
    } 

    render() { 
    return (
     <GeolocationExampleGoogleMap 
     googleMapURL={googleMapURL} 
     loadingElement={<div style={{ height: '100%' }}>loading...</div>} 
     containerElement={<div style={{ height: '100%' }} />} 
     mapElement={<div style={{ height: '100%' }} />} 
     center={this.state.center} 
     content={this.state.content} 
     radius={this.state.radius} 
     onMarkerClick={this.handleMarkerClick} 
     onCloseClick={this.handleCloseClick} 
     markers={this.state.markers} 
     /> 
    ); 
    } 
} 

function mapStateToProps({ browser }) { 
    return { browser }; 
} 

export default connect(mapStateToProps)(OfferMap); 
+0

あなたは 'componentWillMount'ライフサイクル方法を試してみました:だけでなく、このページを見ていますか? –

+0

はい私はこれを試しました –

+0

あなたはcomponentDidMountのsetTimeoutを1秒(これはJavaScript関数です)使ってみましたか? – fungusanthrax

答えて

1

クイックフィックスは...その後

markers: (props.browser.items.length > 0) ? 
generateInitialMarkers(props.browser.items) : "" 

期待小道具が存在しない場合は、あなたの状態でgenerateInitialMarkers()を呼び出していないためにも、まだでしょう.itemsの小道具は、あなたはまた、適切な値が割り当てられるまでthis.state.markersを呼び出してから、あなたのレンダリング()関数/ GeolocationExampleGoogleMapコンポーネントを防ぐために必要があるかもしれません

componentWillReceiveProps(nextProps) { 
    this.setState({ markers: generateInitialMarkers(nextProps.browser.items) }) 
} 

を述べるためにそれらを追加します。

これは少しハッキリです。

さらに望ましい解決策は、OfferMapコンポーネントを呼び出す前に、必要な小道具を渡すことです。


さらに読書

が反応の良い理解を得るために、このページでコンポーネントのライフサイクルを見てみましょう:また

https://facebook.github.io/react/docs/react-component.html

を、それはあなたがしたいとしているように聞こえますredux状態をコンポーネント内のプロパティにマップします。

http://redux.js.org/docs/basics/UsageWithReact.html

+0

あなたが言っていることを正確には分かっていない、 'this.setState({marker:generateMarkers(this.props.browser.items})'をcomponentDidMount()の中に書こうとしていますか?私の答え。 –

+0

私の元の答えを変更しました。それが役に立ったら教えてください。 –

関連する問題