Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Leaflet V3 Custom Control

There's a new react-leaflet version coming which can be found here: npm install react-leaflet/next docs: https://react-leaflet-v3.now.sh/docs/start-introduction

which is a complete re write using hooks.

Based on these new hooks i'm trying to write a custom layer control, which i mainly just want to split into groups and render my react components from material-ui to keep the map styling inline with the rest of my application. The hooks from my understanding get used like the folliwng:

basic control example

const MyControl = Control.extend({
  onAdd: map => {
    let container = DomUtil.create('div');
    container.innerHTML += 'My Control';

    return container;
  },
  // this one is optional
  onRemove: map => {},
});

const useControlElement = createElementHook(
  function createControl(_ref, ctx) {
    const context = useLeafletContext();
    var instance = new MyControl(position);
    return {
      instance: instance,
      context: Object.assign({}, ctx, {
        control: instance,
      }),
    };
  },
  function updateControl(control, props, prevProps) {},
);

const useControl = createControlHook(useControlElement);

const FinalControl = createContainerComponent(useControl);

function ControlComponent({ children }) {
  const controlRef = useRef();
  // if ref exits portal children through, note: using react scripts to support ?
   if(ref.?current?.getContainer()){
     ReactDOM.createPortal(children, ref.current.getContainer())
   }
  return <FinalControl ref={controlRef} />;
}

export default ControlComponent;

However the children are never rendered because controls are only added on componentDidMount.

I want to write this layer control in React/JSX/JS i don't want to have to completely build it using html i.e. L.Control, and using leaflets domutil as this would't work with my react styling anyway and provide restricted access to my redux store. So i'm trying to just portal my component through a basic control like how react-leaflet-control works

Am i approaching this in the right way? i'm just going around in circles atm trying to get this to work in a good way. I'm nearly at the point where i'm just going to render a react component as a child of the map and set the position to absolute (which i know is the wrong way, but does work)

i.e.

<MapContainer>
  <ReactComponent />
</MapContiner>

The documentation has an example for custom components but that's only for leaflet component that already exists, i.e. the square example in the "core architecture" section. Any help appreciated!

like image 763
Dylan Zemek Avatar asked Jul 17 '20 04:07

Dylan Zemek


Video Answer


1 Answers

This can be simplified even further using createControlComponent hook

import { createControlComponent } from "@react-leaflet/core";
import { Control, DomUtil } from "leaflet";

Control.Watermark = Control.extend({
  onAdd: function (map) {
    const img = DomUtil.create("img");
    img.src = "./logo.png";
    img.style.width = "200px";
    return img;
  },

  onRemove: function (map) {},
});

export const WatermarkControl = createControlComponent(
  (props) => new Control.Watermark(props)
);
like image 83
mdseb Avatar answered Nov 25 '22 16:11

mdseb