Задать вопрос
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>
    );
  }
}
  • Вопрос задан
  • 122 просмотра
Подписаться 2 Простой 2 комментария
Помогут разобраться в теме Все курсы
  • Яндекс Практикум
    React-разработчик
    3 месяца
    Далее
  • Merion Academy
    Frontend-разработка на React
    4 месяца
    Далее
  • ProductStar
    React: отточите навыки интерфейсной разработки
    6 недель
    Далее
Пригласить эксперта
Ответы на вопрос 1
alexiusp
@alexiusp
senior frontend developer
Чтобы чайлд-компонент перерисовывался без перерисовки парента, он должен быть привязан к пропсу не через парента. Например через контекст.
Вынесите waypoints в context, например, и рендерите Checkpoint через Consumer.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Похожие вопросы
ITK academy Нижний Новгород
от 50 000 до 90 000 ₽
IT ATLAS Москва
от 200 000 до 250 000 ₽
ITK academy Казань
от 50 000 до 90 000 ₽