2016-04-04 25 views
1

私はその内部にGoogleマップのインスタンスを保持するReactコンポーネントを持っています。 Meteorをインフラストラクチャに使用していますが、問題はReactコンポーネントが同期してレンダリングされることですが、サーバー側の変数を取得するには非同期にする必要があります。この状況を適切に処理するにはどうすればよいでしょうか?ここに私のスニペットは以下です:非同期Meteor.call内の反応コンポーネント

import { Meteor } from 'meteor/meteor'; 
import React from 'react'; 
import { Gmaps, Marker, InfoWindow, Circle } from 'react-gmaps'; 

// Goals for this: 
// - get the location of the user dynamically 
// - see other users as markers 

const coords = { 
    lat: 51.5258541, 
    lng: -0.08040660000006028, 
}; 

export default class App extends React.Component { 
    componentWillMount() { 
    const params = { 
     v: '3.exp', 
     key: null, 
    }; 

    Meteor.call('googleMapsApiKey', (err, res) => { 
     if (!err) { 
     params.key = res; 
     console.log('params', params); 
     } 
    }); 
    } 

    onMapCreated(map) { 
    map.setOptions({ 
     disableDefaultUI: true, 
    }); 
    } 

    onDragEnd(e) { 
    console.log('onDragEnd', e); 
    } 

    onCloseClick() { 
    console.log('onCloseClick'); 
    } 

    onClick(e) { 
    console.log('onClick', e); 
    } 

    onDragStart(e) { 
    console.log('onDragStart', e); 
    } 

    render() { 
    return (
     <Gmaps 
     width={'800px'} 
     height={'600px'} 
     lat={coords.lat} 
     lng={coords.lng} 
     zoom={12} 
     loadingMessage={'Be happy'} 
     params={params} 
     onMapCreated={this.onMapCreated} 
     > 
     <Marker 
      lat={coords.lat} 
      lng={coords.lng} 
      draggable 
      onDragStart={this.onDragStart} 
     /> 
     <InfoWindow 
      lat={coords.lat} 
      lng={coords.lng} 
      content={'Hello, React :)'} 
      onCloseClick={this.onCloseClick} 
     /> 
     <Circle 
      lat={coords.lat} 
      lng={coords.lng} 
      radius={500} 
      onClick={this.onClick} 
     /> 
     </Gmaps> 
    ); 
    } 
} 

ここで同期/非同期の問題を示して証拠コンソールのエラーです:

enter image description here

renderメソッドは非同期応答が発生するのを待つていないようです。これに対処するベストプラクティスは何ですか?バベルのブログから

+0

これはうまくいきましたか? – JordanHendrix

答えて

1

あなたがReact.Componentを使用すると、大きな違いはcomponentwillmountロジックはそうのようなクラスのコンストラクタに置かれるべきであるということである

ライフサイクルメソッドのすべて新しいクラス構文を使用するときに期待するように定義することができます。クラスのコンストラクタは、以前componentWillMountで満たされた役割を前提としています

// The ES5 way 
var EmbedModal = React.createClass({ 
    componentWillMount: function() { … }, 
}); 
// The ES6+ way 
class EmbedModal extends React.Component { 
    constructor(props) { 
    super(props); 
    // Operations usually carried out in componentWillMount go here 
    } 
} 

Link to blog post

2

あなたが反応コンポーネントを設計するとき、あなたはそれを持っている可能性があり、複数の状態を考える必要があります。たとえば、マップを表示する前にGoogleマップコンポーネントを読み込む必要があります。そのため、読み込みと読み込みの2つの状態があります。それはあなたの流星呼び出しの結果のキーに依存します:

export default class App extends React.Component { 

    constructor(props) { 
    super(props); 

    this.state = { 
     v: '3.exp', 
     key: null 
    }; 

    Meteor.call('googleMapsApiKey', (err, res) => { 
     if (!err) { 
     this.setState({ key: res }) 
     } 
    }); 
    } 

    ... 

    render() { 
    if (this.state.key) { 
     return (
     <Gmaps 
      width={'800px'} 
      height={'600px'} 
      lat={coords.lat} 
      lng={coords.lng} 
      zoom={12} 
      loadingMessage={'Be happy'} 
      params={this.state} 
      onMapCreated={this.onMapCreated} 
     > 
      <Marker 
      lat={coords.lat} 
      lng={coords.lng} 
      draggable 
      onDragStart={this.onDragStart} 
      /> 
      <InfoWindow 
      lat={coords.lat} 
      lng={coords.lng} 
      content={'Hello, React :)'} 
      onCloseClick={this.onCloseClick} 
      /> 
      <Circle 
      lat={coords.lat} 
      lng={coords.lng} 
      radius={500} 
      onClick={this.onClick} 
      /> 
     </Gmaps> 
    ); 
    } else { 
     return <div>Loading...</div>; 
    } 
    } 
} 

基本的に、私はちょうど状態でconst paramsあなたの置き換えに加えて、いくつかのロード管理を追加しました。 ES6コンポーネントでは、コンストラクタにthis.stateを宣言する必要があります。

+0

これは答えに近いと感じますが、残念なことにMeteorは非同期呼び出しを返す前にコンポーネントをレンダリングしていますので、「no api keys」に関する警告メッセージが表示されます。 – ilrein

関連する問題