jgimbel / react-leaflet-div-icon

marker that will use children as the content if the marker.
ISC License
28 stars 24 forks source link

Update for React Leaflet 2.0 #20

Open kevinhughes27 opened 6 years ago

kevinhughes27 commented 6 years ago

This package crashes with React Leaflet 2.0:

Uncaught TypeError: Cannot read property 'call' of undefined
    at Divicon.componentWillMount (index.js:141)
kevinhughes27 commented 5 years ago

I solved this a different way in case it helps anyone

import * as React from 'react';
import { divIcon } from 'leaflet';
import { Marker } from 'react-leaflet';

const MapLabel = () => {
  const icon = divIcon({
    className: 'map-label',
    html: `<span>Label Text</span>`
  });

  return (
    <Marker
      position={{ lat: 90, lng: 90 }}
      icon={icon}
    />
  );
};
timburgess commented 5 years ago

You can put svg directly into the "html" property as well to directly render svg on your map.

For an example svg marker with value, see https://codepen.io/timburgess/pen/zeOqrr

rseyferth commented 5 years ago

Here's my implementation of a JSX marker:

import React from 'react';
import {divIcon} from "leaflet";
import PropTypes from 'prop-types';
import {Marker} from "react-leaflet";

class JsxMarkerContent extends React.Component {

    onRef(ref) {

        if (ref) {
            const html = ref.innerHTML;
            if (html !== this.previousHtml) {
                this.props.onRender(html);
                this.previousHtml = html;
            }

        }
    }

    render() {
        return (
            <div className="jsx-marker" style={{ display: 'none' }} ref={this.onRef.bind(this)}>
                {this.props.children}
            </div>
        );
    }

}

class JsxMarker extends React.Component {

    static propTypes = {
        position: PropTypes.object,
        className: PropTypes.string
    };

    constructor(props) {
        super(props);
        this.state = {
            html: null
        };
    }

    onInsideRender(html) {

        // Set it
        this.setState({ html });

    }

    render() {

        const { html } = this.state;
        let marker = false;
        if (html) {

            // Create divIcon
            const icon = divIcon({
                className: this.props.className,
                html
            });
            marker = <Marker position={this.props.position} icon={icon} {...this.props} />

        }

        return (<React.Fragment>

            <JsxMarkerContent onRender={html => this.onInsideRender(html)}>
                {this.props.children}
            </JsxMarkerContent>

            {marker}

        </React.Fragment>);

    }

}

export default JsxMarker;

I haven't been using React for ages, so any comments or suggestions are welcome!