Правильный способ обновления реквизита с помощью Mapbox - PullRequest
1 голос
/ 06 марта 2019

Как правильно удалить и добавить источник / слои с помощью Mapbox? Я использую React, и у меня возникают проблемы, и я получаю сообщение об ошибке при обновлении источника data prop. Насколько я прочитал в документации Mapbox removeSource следует удалить его перед повторным добавлением, но он не работает при обновлении компонента.

Ошибка: источник с таким идентификатором уже существует

  componentDidMount() {
    const { data } = this.props;
    this.map = new mapboxgl.Map(config);
  }

  componentWillUnmount() {
    const map = this.map;
    map.remove();
    map.removeControl(Draw, 'top-left');
  }


  shouldComponentUpdate(props, nextProps) {
    const { data } = props;
    if (JSON.stringify(data) !== JSON.stringify(nextProps.data)) {
      return true;
    }
    return false;
  }


  componentDidUpdate(prevProps) {
    const { data } = this.props;
    if (JSON.stringify(data) !== JSON.stringify(prevProps.data)) {
      this.fetchMap();
    }
  }

  fetchMap() {
        const map = this.map;
        const { data } = this.props;
        map.addControl(Draw, 'top-left');

        map.on("load", (e) => {
            if (data.features !== null) {

                if (map.getSource("locations")) {
                    map.removeSource("locations");
                }

                map.addSource("locations", {
                    type: "geojson",
                    data: data
                });
            }
        })
  }

1 Ответ

0 голосов
/ 12 марта 2019

Проблема в том, что вы вызываете map.addSource несколько раз в течение жизненного цикла вашего компонента.

Если я правильно понял, чего вы пытаетесь достичь, то вам нужно переместить обработчик событий load вашей карты вcomponentDidMount method:

componentDidMount() {
  const { data } = this.props;

  const map = new mapboxgl.Map(config);
  map.addControl(Draw, 'top-left');

  map.once("load", (e) => {
    map.addSource("locations", {
        type: "geojson",
        data: data
    });

    this.setState({ mapIsLoaded: true });
  });

  this.map = map;
}

Обратите внимание на использование map.once вместо map.on и установку mapIsLoaded переменной состояния после завершения загрузки карты.

Теперь выможет обработать ваше обновление источника на componentDidUpdate после загрузки карты:

componentDidUpdate(prevProps) {
  const { data } = this.props;
  const { mapIsLoaded } = this.state;

  if (!mapIsLoaded) {
    return;
  }

  if (data !== prevProps.data) {
    this.map.getSource("locations").setData(data);
  }
}

Вот и все.


Кстати, я автор React ComponentБиблиотека для Mapbox GL JS .Предполагается, что проект будет максимально приближен к API Mapbox GL JS.

Например, вот как вы можете переписать свой код в библиотеке:

<MapGL mapStyle='mapbox://styles/mapbox/light-v9'>
  <Source id='locations' type='geojson' data={data} />
  <Layer
    id='locations'
    type='circle'
    source='locations'
    paint={{
      'circle-radius': 6,
      'circle-color': '#1978c8'
    }}
  />
  <Draw />
</MapGL>
...