Source: components/userComponents/maps/MonitoredAreaMap.js

import React from "react";
import { SimpleHereMap } from './SimpleHereMap';
import {
  ValidateLatitude,
  ValidateLongitude
} from '../../validationModules/MonitoredAreaFormValidationModule';
import { withNamespaces } from 'react-i18next';

/**
 * Map for displaying monitored area location
 * @extends Component
 * @hideconstructor
 */
class MonitoredAreaMap extends React.Component {

  /**
   * @constructs
   * @param props
   */
  constructor(props) {
    super(props);
    /* Initialize React ref to map */
    this.hereMap = React.createRef();
    this.state = {
      initial : null,
      searchAddress : "",
      isAddressValid : true
    };
    this.deviceMarker = null;
    this.setInicialPosition = false;
  }

  static defaultProps = {
    deviceLatitude : null,
    deviceLongitude : null
  };

  /**
   *
   */
  saveChanges(){
    let position = this.deviceMarker.getPosition();
    this.props.saveChanges(position.lat, position.lng);
  }

  /**
   *
   */
  updateMap(){

    //if we have marker, draw marker
    if (this.deviceMarker !== null) {
      this.hereMap.current.removeObjectFromMap(this.deviceMarker);
      this.deviceMarker = null;
    }
      //else f we have props, create marker from props and draw
    if (this.props.deviceLatitude !== undefined && this.deviceLongitude !== null){
      if (ValidateLatitude(this.props.deviceLatitude) && ValidateLongitude(this.props.deviceLongitude)) {
        let coords = {
          "lat": this.props.deviceLatitude,
          "lng": this.props.deviceLongitude
        }

        let marker = new window.H.map.Marker(coords);
        this.hereMap.current.addObjectToMap(marker);
        this.deviceMarker = marker;
      }
    }
  }

  /**
   *
   * @param event
   */
  onMapClick = (event) => {
    //clear old marker if there is any
    this.setInicialPosition = true;
    if (this.deviceMarker !== undefined && this.deviceMarker !== null)
      this.hereMap.current.removeObjectFromMap(this.deviceMarker);

    //make new marker
    let coords = this.hereMap.current.screenToGeo(event.currentPointer.viewportX, event.currentPointer.viewportY);
    let marker = new window.H.map.Marker(coords);

    this.deviceMarker = marker;
    this.hereMap.current.addObjectToMap(this.deviceMarker);

    this.saveChanges();
  };

  /**
   *
   * @param prevProps
   * @param prevState
   * @param snapshot
   */
  componentDidUpdate(prevProps, prevState, snapshot) {
    if (prevProps === this.props) return;

    if (this.props.deviceLatitude !== null && this.props.deviceLongitude !== null
      && this.props.deviceLatitude !== "" && this.props.deviceLongitude !== ""
      && this.setInicialPosition === false) {
      this.setState({
        initial: {
          lat : this.props.deviceLatitude,
          lng : this.props.deviceLongitude
        }
      })
      this.setInicialPosition = true;
    }

    this.updateMap();
  }

  /**
   *
   */
  componentDidMount() {
    if (this.props.interactive !== undefined && this.props.interactive === false) return;
    this.hereMap.current.addEventListenerToMap('pointerdown', this.onMapClick)
    //this.hereMap.current.resizeViewPort();
  }

  /**
   *
   */
  componentWillUnmount() {
    if (this.props.interactive !== undefined && this.props.interactive === false) return;
    this.hereMap.current.removeEventListenerFromMap('pointerdown', this.onMapClick);
  }

  /**
   *
   * @param event
   */
  locateAddress = (event) => {
    event.preventDefault(event);
    this.hereMap.current.geocode(this.state.searchAddress);
  }

  /**
   *
   * @param result
   */
  onAddressFound = (result) => {
    if (result === null) {
      this.setState({
        isAddressValid : false

      });
      return;
    }
    this.setState({
      isAddressValid : true
    });
    this.hereMap.current.setCenter(result[0].location.displayPosition.latitude, result[0].location.displayPosition.longitude)
    this.hereMap.current.setZoom(18);
  }

  /**
   *
   * @param event
   */
  onAddressChange = (event) => {
    const target = event.target;
    const value = target.value;

    this.setState({
      searchAddress : value,
    });
  }

  /**
   *
   * @returns {*}
   */
  render() {
    const { t } = this.props;
    let map = null;
    if (this.state.initial === null) {
      map = <SimpleHereMap width="100%" height="300px" ref={this.hereMap}
                           onGeocodeSuccess={this.onAddressFound}
      />
    }else{
      map = <SimpleHereMap width="100%" height="300px" ref={this.hereMap}
                           lat={Number(this.state.initial.lat)}
                           lng={Number(this.state.initial.lng)}
                           zoom={16}
                           onGeocodeSuccess={this.onAddressFound}
      />
    }

    let address = null;
    if (this.props.interactive !== undefined && this.props.interactive === true) {
      address = <div className="row">
        <div style={{margin: 'inherit'}}>
          <div className={this.state.isAddressValid ? "form-group col-sm-5" : "form-group has-error col-sm-5"}>
            <input
              style={{height: '30px'}}
              type="text"
              className="form-control"
              placeholder={t("maps.typeAddressHere")}
              name="address"
              value={this.state.searchAddress}
              onChange={(e) => this.onAddressChange(e)}
            />
          </div>
          <button className="btn-sm btn-primary col-sm-2" style={{height: '30px'}}
                  onClick={(event) => this.locateAddress(event)}
          >{t("maps.goToAddress")}</button>
        </div>
      </div>
    }else address = "";

    return (
      <div>
        {address}
        <div className="row">
          {map}
        </div>
      </div>
    )
  }
}

export default withNamespaces()(MonitoredAreaMap);