Задать вопрос
dmc1989
@dmc1989

Как правильно обновлять количество чекпоинтов?

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

interface MapControllerProps {
  getCoords?: ({lng, lat}: {lng: number, lat: number}) => any,
  onStyleLoad?: (map: any) => void,
  onLoad?: (map: any) => void,
  onMouseMove?: (map: any) => void,
  waypoints?: Coordinates[]
}

class MapController extends Component<MapControllerProps> {
  zoomControl = (map: any) => {
    if (map.getZoom() <= 16) {
      map.flyTo({
        pitch: 0,
        bearing: 0
      });
    } else {
      map.flyTo({
        pitch: 65,
        bearing: 20
      });
    }
  }

  shouldComponentUpdate(nextProps) {
    if (!this.props.waypoints) {
      return false;
    }

    if (this.props.waypoints.length != nextProps.waypoints.length) {
      // Map = ReactMapboxGl({
      //   accessToken: ENVIRONMENT.mapbox.accessToken
      // });
      return true;
    } else {
      return false;
    }

    return false;
  }

  render() {
    return (
      <div id="map-container">
        <Map
          style="mapbox://styles/mapbox/streets-v8"
          containerStyle={{
            height: '100%',
            width: '100%'
          }}
          center={[car3DModelLayer.coordinates.lat, car3DModelLayer.coordinates.lng]}
          zoom={[17]}
          pitch={[65]}
          bearing={[20]}
          onZoom={this.zoomControl}
          onStyleLoad={this.props.onStyleLoad}
          onMouseMove={this.props.onMouseMove}
        >
          <MapContext.Consumer>
            {(map: any): any => {
              this.props.onLoad ? this.props.onLoad(map) : null;
            }}
          </MapContext.Consumer>
          <ScaleControl position="top-right"/>
          <BuildingsLayer3DComponent />
          <div>{this.props.children}</div>
        </Map>
      </div>
    );
  }
}

interface Coordinates {
  lng: number,
  lat: number
}

interface MapComponentState {
  currentCoordinates?: Coordinates,
  checkedCoordinates: Coordinates,
  waypoints: Coordinates[]
}

class MapComponent extends Component<{}, MapComponentState> {
  state = {
    checkedCoordinates: { lng: 0, lat: 0 },
    waypoints: [{lat: 24.03862, lng: 49.83498}]
  }

  getCoords = (coords: {lat: number, lng: number}) => {
    console.log("hui")
    this.setState({ checkedCoordinates: coords });
  }

  addWaypoint = () => {
    if (this.state.checkedCoordinates.lng == 0 && this.state.checkedCoordinates.lat == 0) {
      alert("Enter norm coordinates!");
    } else {
      this.setState({
        waypoints: this.state.waypoints.concat(this.state.checkedCoordinates)
      });
    }
  }

  add3DObject(object: Object3DLayer, map: any) {
    try {
      map.addLayer(object, "waterway-label");
    } catch (err) {
      console.error(err);
    }
  }

  getRoute() {
    axios
      .get(`https://api.mapbox.com/directions/v5/mapbox/driving/-122.42,37.78;-77.03,38.91?access_token=${ENVIRONMENT.mapbox.accessToken}`)
      .then(({data}) => {
        console.log(data);
      })
      .catch(err => {
        console.error(err);
      })
  }

  declareIcon(opts: { path: string, title: string}, map: any) {
    map.loadImage(opts.path, (err, image) => {
      if (err) {
        console.error(err);
      } else {
        try {
          map.addImage(opts.title, image);
        } catch (err) {
          console.error(err);
        }
      }
    });
  }

  

  handleMapClick(map: any) {
    map.on('mousedown', (e: any) => {
      try {
        this.setState({ checkedCoordinates: e.lngLat.wrap() });
      } catch (err) {
        console.error(err);
      }
    });
  }

  componentDidUpdate() {
    console.log(this.state.waypoints);
  }

  handleMapLoad = (map: any) => {
    this.declareIcon({path: '/img/map-marker-icon.png', title: 'map-marker-icon'}, map);
    this.handleMapClick(map);
  }

  handleMapStyleClick = (map: any) => {
    try {
      this.add3DObject(car3DModelLayer, map);
    } catch (err) {
      console.error(err);
    }
  }

  render() {
    return(
      <div>
        <MapController waypoints={this.state.waypoints} onStyleLoad={this.handleMapStyleClick} onLoad={this.handleMapLoad} getCoords={this.getCoords}>
          <Checkpoint textColor="#ffffff" icon="map-marker-icon" iconScale={0.15} points={this.state.waypoints} />
        </MapController>
        <RoutingForm handleClick={this.addWaypoint} lat={this.state.checkedCoordinates.lat} lng={this.state.checkedCoordinates.lng} />
      </div>
    );
  }
}
  • Вопрос задан
  • 119 просмотров
Подписаться 2 Простой 2 комментария
Пригласить эксперта
Ответы на вопрос 1
alexiusp
@alexiusp
senior frontend developer
Чтобы чайлд-компонент перерисовывался без перерисовки парента, он должен быть привязан к пропсу не через парента. Например через контекст.
Вынесите waypoints в context, например, и рендерите Checkpoint через Consumer.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы