title: How can I drag and drop objects into a Mapbox map from outside the map?
body: <p>How can I create elements outside of a <a href="https://docs.mapbox.com/mapbox-gl-js/api/map/#map" rel="nofollow noreferrer">Mapbox map object</a> that can be dragged into it? For example, let's say I want to render a list of locations on a page. Each location is a React component with a custom marker or icon.</p>
  <p>Next to this list of locations is a Mapbox map. The list of locations is not rendered inside the map. While I know it's possible to make these individual location components draggable, is it possible to drag and drop them into a Mapbox map and have it recognized as actual markers with latitude/longitude coordinates on the map? If so, how can I do this?</p>
  <p>Here are the relevant source files in my code that I have tried:</p>
  <p><strong>index.js</strong></p>
  <pre><code>import dynamic from &quot;next/dynamic&quot;;
  import { useSelector } from &quot;react-redux&quot;;
  import Plant from &quot;../../components/Plant&quot;;
  
  const MapboxMap = dynamic(() =&gt; import(&quot;../../components/MapboxGLMap&quot;), {
    ssr: false,
  });
  
  const Blueprint = () =&gt; {
    const plants = useSelector((state) =&gt; state.plants);
  
    const showPlants = () =&gt; {
      return (
        &lt;React.Fragment&gt;
          {plants.map((plant) =&gt; (
            &lt;Plant plant={plant} /&gt;
          ))}
        &lt;/React.Fragment&gt;
      );
    };
  
    return (
      &lt;React.Fragment&gt;
        &lt;div className=&quot;ui container centered grid blueprint&quot;&gt;
          &lt;div className=&quot;three wide column scrollable&quot;&gt;
            &lt;div className=&quot;ui link one cards&quot;&gt;{showPlants()}&lt;/div&gt;
          &lt;/div&gt;
          &lt;div className=&quot;twelve wide column&quot;&gt;
            &lt;MapboxMap /&gt;
          &lt;/div&gt;
        &lt;style jsx&gt;{`
          .scrollable {
            height: calc(100vh);
            overflow-x: auto;
          }
        `}&lt;/style&gt;
      &lt;/React.Fragment&gt;
    );
  };
  
  export default Blueprint;
  
  </code></pre>
  <p><strong>Plant.jsx</strong></p>
  <pre><code>import React from &quot;react&quot;;
  import { useDrag } from &quot;react-dnd&quot;;
  
  const ItemTypes = {
    PLANT: &quot;plant&quot;,
  };
  
  const Plant = ({ plant }) =&gt; {
    const [{ isDragging }, drag] = useDrag({
      item: { type: ItemTypes.PLANT },
      collect: (monitor) =&gt; ({
        isDragging: !!monitor.isDragging(),
      }),
    });
    return (
      &lt;div
        ref={drag}
        style={{
          opacity: isDragging ? 0.1 : 1,
          cursor: &quot;move&quot;,
        }}
        key={plant.id}
        className=&quot;card&quot;
      &gt;
        &lt;div className=&quot;image&quot;&gt;
          &lt;img src=&quot;/white-image.png&quot; /&gt;
        &lt;/div&gt;
        &lt;div className=&quot;content&quot;&gt;
          &lt;div className=&quot;center aligned&quot;&gt;{plant.common_name}&lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    );
  };
  
  export default Plant;
  </code></pre>
  <p><strong>MapboxGLMap.jsx</strong></p>
  <pre><code>import React, { useEffect, useRef, useState } from &quot;react&quot;;
  import mapboxgl from &quot;mapbox-gl&quot;;
  import MapboxGeocoder from &quot;@mapbox/mapbox-gl-geocoder&quot;;
  import MapboxDraw from &quot;@mapbox/mapbox-gl-draw&quot;;
  
  const MAPBOX_TOKEN = &quot;xxx&quot;;
  
  const styles = {
    width: &quot;100%&quot;,
    height: &quot;100%&quot;,
    position: &quot;absolute&quot;,
  };
  
  const MapboxGLMap = () =&gt; {
    const [map, setMap] = useState(null);
    const [lng, setLng] = useState(null);
    const [lat, setLat] = useState(null);
    const [plant, setPlant] = useState(null);
  
    const mapContainer = useRef(null);
  
    useEffect(() =&gt; {
      mapboxgl.accessToken = MAPBOX_TOKEN;
      const initializeMap = ({ setMap, mapContainer }) =&gt; {
        const map = new mapboxgl.Map({
          container: mapContainer.current,
          style: &quot;mapbox://styles/mapbox/satellite-v9&quot;, // stylesheet location
          center: [0, 0],
          zoom: 5,
        });
  
        map.on(&quot;load&quot;, () =&gt; {
          setMap(map);
          map.resize();
        });
  
        map.on(&quot;click&quot;, (e) =&gt; {});
  
        map.addControl(
          new MapboxGeocoder({
            accessToken: MAPBOX_TOKEN,
            mapboxgl: mapboxgl,
          })
        );
  
        const draw = new MapboxDraw({
          displayControlsDefault: false,
          controls: {
            polygon: true,
            trash: true,
          },
        });
        map.addControl(draw);
  
        map.on(&quot;draw.create&quot;, (e) =&gt; {
          console.log(&quot;e =&gt;&quot;, e);
          console.log(&quot;draw.getAll()&quot;, draw.getAll());
        });
  
        map.on(&quot;mousemove&quot;, (e) =&gt; {
          // console.log(e.point);
          setLng(e.lngLat.wrap().lng);
          setLat(e.lngLat.wrap().lat);
        });
      };
  
      if (!map) initializeMap({ setMap, mapContainer });
    }, [map]);
  
    return &lt;div ref={(el) =&gt; (mapContainer.current = el)} style={styles} /&gt;;
  };
  
  export default MapboxGLMap;
  </code></pre>