Маркеры React google maps исчезают после повторного рендеринга компонента

У меня проблемы с модулем react-google-maps, а именно с маркерами и повторным рендерингом компонентов.

Это сценарий:

  1. Загрузить страницу с картой и 2-3 маркерами на ней (ок)
  2. Щелкните вкладку на панели навигации -> страница отображает что-то еще в стиле одностраничного приложения (хорошо)
  3. Щелкните вкладку на панели навигации, которая ведет обратно к карте -> страница отображает карту, но маркеры не отображаются.

Я храню данные маркеров в состоянии и применяю их к карте в onGoogleApiLoaded={({map, maps}) => this.renderMarkers(map, maps)}.

Мне удалось решить эту проблему, заключив renderMarkers в setTimeout за одну секунду, и таким образом он отлично загружается.

Мне не нравится это решение, и я считаю, что просто не делаю его так, как должен. Я считаю, что маркеры пытаются разместить себя на карте, которая не отображается, но любопытно, что даже безsetTimeout он работает для страницы по умолчанию (возможно, что-то связано с жизненным циклом реагирующего компонента, я не знаю).

Есть ли способ прикрепить свойство onGoogleApiLoaded={({map, maps}) => this.renderMarkers(map, maps)} после полной загрузки карты? Или, по крайней мере, отложите это до тех пор, пока я не буду на 100% уверен, что карта загружена, а не какое-то случайное количество секунд.

РЕДАКТИРОВАТЬ: я назначал маркеры с помощью метода marker.setMap(map), и я просто попытался настроить свойство map: map в конструкторе маркера, но поведение осталось прежним.


person Edeph    schedule 07.06.2018    source источник


Ответы (2)


Я понял это после того, как немного разобрался с проблемой. Проблема была вызвана тем, что я терял данные маркера, которые хранились в состоянии компонента Map (который является дочерним по отношению к компоненту, имеющему панель навигации).

Итак, поток был таким:

  1. Первый рендеринг страницы -> все загружается нормально, потому что все отображается впервые (включая маркеры).
  2. Я визуализирую другой компонент, предыдущий разрушается и теряет состояние.
  3. Я повторно визуализирую компонент Map, но у него нет состояния, поэтому у него нет данных для использования маркерами.

Естественно, решение заключалось в том, чтобы переместить состояние на один уровень выше в родительский и передать его как опору компонента Map, и теперь все работает так, как должно.

БОНУС:

Я хочу упомянуть еще одну вещь, которую мне нужно было исправить, но она не обязательно будет полезна для других, которые столкнутся с этой проблемой: я использовал панель навигации для маршрутизации по своим страницам (используя react-router-dom).

При перемещении состояния на уровень выше в родительский, параметры не будут переданы элементу <Route следующим образом: <Route path="/" component={Map} markerData={this.state.markerData}/>, а будут использовать свойство render, например: <Route exact path="/" render={props => <Map markerData={this.state.markerData}/>}, чтобы компонент Map получил свойства, а не Router.

person Edeph    schedule 07.06.2018

Когда вы говорите, что щелкаете вкладку, и на странице отображается что-то еще, вы, вероятно, отключаете компонент карты. Если ваши маркеры сохранены в том состоянии, в котором вы говорите, вы можете проверить это самостоятельно в componentWillUnmount.

componentWillUnmount() {
  console.log('Unmount');
}

Если этот журнал консоли отображается в вашей консоли, это означает, что вы отключаете свой компонент и теряете данные маркеров, которые есть в вашем состоянии.

Теперь, чтобы загрузить карту с вашими маркерами, вы можете дождаться полной загрузки карты с помощью componentDidMount. Я не уверен, чем response-google-maps отличается от response-leaflet (компонент карты, с которым у меня есть опыт), но я предполагаю, что у карты есть свойство, в котором вы передаете ему маркеры, которые вы сохраняете в состоянии. Вместо тайм-аута вам, вероятно, следует использовать componentWillMount или componentDidUnmount метод реагирования на жизненный цикл для получения данных ваших маркеров.

componentDidMount() { // It should work with componentWillMount too
  this.fetchMarkersData();
}

fetchMarkersData() {
  // ... get your data
  this.setState({ markers: markersData });
}

render() {
  return (
    <MapComponent
      markers={this.state.markers}
    />
  );
}
person Rodius    schedule 07.06.2018
comment
Да, мой компонент карты отключается, что является ожидаемым поведением. И я уже делаю то, что ты сказал. Проблема заключается в момент добавления маркеров на карту, а не при создании экземпляров маркеров. Я начинаю думать, что должен попытаться добавить их с помощью свойства маркера map: map,. - person Edeph; 07.06.2018