Toni BCN
Toni BCN

Reputation: 392

How to use react-leaflet v3 to create class components?

React-leaflet package allows to use leaflet and react using functional components, at least all the examples at https://react-leaflet.js.org/ are using functional components. Is possible to use class components with version 3 of react-leaflet? If yes, there are examples?

Upvotes: 3

Views: 1663

Answers (1)

Vadim Gremyachev
Vadim Gremyachev

Reputation: 59338

It is supported to create a class components in react-leaflet v3 although not the same way as it was officially supported in previous versions.

In version v1 and v2 you were suppose to implement a custom component by:

a) extending one of the abstract classes provided by react-leaflet, for example:

class MapInfo extends MapControl {
   //...
} 

b) and implementing createLeafletElement (props: Object): Object method

Refer this answer for a more details since official documentation for implementing custom components for v1 and v2 versions is no longer available.


The following example demonstrates how to convert custom component into version 3.

Here is an a custom component compatible with v1/v2 version:

import React, { Component } from "react";
import { withLeaflet, MapControl } from "react-leaflet";
import L from "leaflet";

class MapInfo extends MapControl {
  constructor(props, context) {
    super(props);
    props.leaflet.map.addEventListener("mousemove", ev => {
      this.panelDiv.innerHTML = `<h2><span>Lat: ${ev.latlng.lat.toFixed(
        4
      )}</span>&nbsp;<span>Lng: ${ev.latlng.lng.toFixed(4)}</span></h2>`;
      console.log(this.panelDiv.innerHTML);
    });
  }

  createLeafletElement(opts) {
    const MapInfo = L.Control.extend({
      onAdd: map => {
        this.panelDiv = L.DomUtil.create("div", "info");
        return this.panelDiv;
      }
    });
    return new MapInfo({ position: "bottomleft" });
  }

  componentDidMount() {
    const { map } = this.props.leaflet;
    this.leafletElement.addTo(map);
  }
}

export default withLeaflet(MapInfo);

which could be converted into the following class component compatible with version 3:

class MapInfo extends React.Component {
 
  createControl() {
    const MapInfo = L.Control.extend({
      onAdd: (map) => {
        const panelDiv = L.DomUtil.create("div", "info");

        map.addEventListener("mousemove", (ev) => {
          panelDiv.innerHTML = `<h2><span>Lat: ${ev.latlng.lat.toFixed(4)}</span>&nbsp;<span>Lng: ${ev.latlng.lng.toFixed(4)}</span></h2>`;
          console.log(panelDiv.innerHTML);
        });
        return panelDiv;
      },
    });
    return new MapInfo({ position: "bottomleft" });
  }

  componentDidMount() {
    const {map} = this.props;
    const control = this.createControl();
    control.addTo(map);
  }

  render() {
    return null;
  }
}

function withMap(Component) {
  return function WrappedComponent(props) {
    const map = useMap();
    return <Component {...props} map={map} />;
  };
}

export default withMap(MapInfo);

Note: withMap is a high order component which is intended to pass map instance into class component

Here is a demo

Upvotes: 5

Related Questions