Stack Exchange
Overlays in OpenLayers with React.js
With React.js 16 and OpenLayers 6.5 I created a component which displays a map with an overlay:
import React from "react";
import OSM from "ol/source/OSM";
import TileLayer from "ol/layer/Tile";
import Map from "ol/Map";
import View from "ol/View";
import Overlay from "ol/Overlay";

class Map extends React.Component {
  constructor(props) {
    super(props);
    this.mapRef = React.createRef();
    this.overlayRef = React.createRef();
  }

  componentDidMount() {
    this.map = new Map({
      layers: [
        new TileLayer({
          source: new OSM(),
        }),
      ],
      target: this.mapRef.current,
      view: new View({
        center: [800000, 5000000],
        zoom: 5,
      }),
    });

    const overlay = new Overlay({
      position: [800000, 5000000],
      element: this.overlayRef.current,
    });
    this.map.addOverlay(overlay);
  }
  render() {
    return (
      <>
        <div ref={this.mapRef} id="map"></div>
        <div ref={this.overlayRef}>Overlay</div>
      </>
    );
  }
}

export default Map;

This code works fine until the component gets unmounted. Then I receive the error
Uncaught DOMException: Node.removeChild: The node to be removed is not a child of this node

and the app crashes. I guess it happens because OpenLayers is modifying the DOM structure and thus React gets confused.
Does anybody knows how to add an overlay which does not modify the DOM structure? Or any other solution to circumvent the problem?

Instead of predefining elements for an overlay you could dynamically create new divs as in https://openlayers.org/en/latest/examples/measure.html

@Mike but what if you want a React Element as overlay?

The problem is that OL Overlay class takes the passed in element this.overlayRef.current and appends it as child to its internal element changing the DOM structure. You can anticipate this and preemptively place your custom overlay element inside Overlay's internal element using React portal:
ReactDOM.createPortal((<div>Overlay</div>), overlay.element)

