Skip to content

Instantly share code, notes, and snippets.

@karantza
Created June 27, 2018 23:01
Show Gist options
  • Save karantza/0212c05eeac090d72a8f00e714f57788 to your computer and use it in GitHub Desktop.
Save karantza/0212c05eeac090d72a8f00e714f57788 to your computer and use it in GitHub Desktop.
Draggable Marker Example
import React from "react";
import PropTypes from "prop-types";
import * as MapboxGl from "mapbox-gl";
export default class DraggableMarker extends React.Component {
marker = null;
componentDidMount() {
const { map } = this.context;
this.marker = new MapboxGl.Marker({
draggable: this.props.draggable,
element: this.refs.wrapper
})
.setLngLat([this.props.coordinate.lon, this.props.coordinate.lat])
.addTo(map);
this.marker.on('drag', () => {
const lngLat = this.marker.getLngLat();
this.props.onDrag && this.props.onDrag(lngLat);
});
}
componentWillUnmount() {
this.marker.remove();
this.marker = null;
}
componentDidUpdate() {
this.marker.setDraggable(this.props.draggable);
}
render() {
return <div ref="wrapper">{this.props.children}</div>
}
}
DraggableMarker.contextTypes = {
map: PropTypes.object
};
<ReactMapboxGl>
<DraggableMarker
draggable
coordinate={{lat: 0, lon: 0}}
onDrag={console.log}
>
<div>I'm a draggable marker!</div>
</DraggableMarker>
</ReactMapboxGl>
@jimhill
Copy link

jimhill commented Jun 15, 2020

Thanks @karantza For anyone else that might stumble upon this here's a quick functional version

import React, { useEffect } from 'react';
import * as MapboxGl from 'mapbox-gl';

const DraggableMarker = ({
  map,
  coordinates,
  draggable,
  onDrag,
  onDragEnd,
  children,
}) => {
  const marker = new MapboxGl.Marker({ draggable })
    .setLngLat(coordinates)
    .addTo(map);

  marker.on('drag', () => {
    onDrag && onDrag(marker.getLngLat());
  });

  marker.on('dragend', () => {
    onDragEnd && onDragEnd(marker.getLngLat());
  });

  useEffect(() => {
    return () => {
      marker.remove();
    };
  }, []);

  return <div>{children}</div>;
};

@karantza
Copy link
Author

karantza commented Jun 15, 2020

Thanks for that update @jimhill!

Doesn't the Marker still need an element reference though? I would expect something like:

const element = useRef(null);
useEffect(() => { 
   const marker = new MapboxGl.Marker({ draggable, element: element.current })
   // rest of marker setup/teardown
}, []);
return <div ref={element}>{children}</div>;

@jimhill
Copy link

jimhill commented Jun 16, 2020

Yes it does. I forgot to update as I also needed to useState rather than useRef as the ref isn’t set. I’ll update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment