Маркеры 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 в конструкторе маркера, но поведение осталось прежним.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
0
1 660
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

componentWillUnmount() {
  console.info('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}
    />
  );
}

Да, мой компонент карты отключается, что является ожидаемым поведением. И я уже делаю то, что ты сказал. Проблема заключается в момент, когда маркеры добавляются на карту, а не когда маркеры создаются. Я начинаю думать, что мне нужно попытаться добавить их с помощью свойства маркера map: map,.

Edeph 07.06.2018 13:56
Ответ принят как подходящий

Я понял это после того, как немного разобрался с проблемой. Проблема была вызвана тем, что я терял данные маркера, которые хранились в состоянии компонента 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.

Другие вопросы по теме