Reputation: 23
Im trying to implement a custom DrawControl with mapbox-gl-js with Next 14 In the Dev Enviroment im using React Strict Mode so my useEffect's render twice.
Now i want to create the Control with the Mapbox useControl hook. After i've set my useRef with the new Control i want to add the Control to the map (without this step i get multiple errors, when trying to use the control with its functions)
After that i want to add a array of features to my custom DrawControl. I've a custom logic for the draw Control.
And its working. The Items get added but then im in a infinite loop with the errormessage There is already a source with this ID. so theirfore there is an error, because "mapRef.current.addControl(drawControl) gets called multiple times. But why? :(
My useEffect dep arrays are emty theirfore it should run only twice (strict mode) otherwise once
Thanks your ur help I wasted 8h at this problem :)
import MapboxDraw from '@mapbox/mapbox-gl-draw';
import { useCallback, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import { useControl, useMap } from 'react-map-gl';
import * as MapboxDrawWaypoint from './utils/custom-prevent-control';
import DrawControl from './draw-control';
export default function DrawControlContainer({ container = {}, child = {} }) {
const { onCreate, onUpdate, onDelete, onActive, clearChangeRange } = container;
const { initialData = [] } = child;
const mapRef = useMap();
const drawRef = useRef(null);
// Custom Draw behaviour
let { modes } = MapboxDraw;
modes = MapboxDrawWaypoint.enable(modes);
// ----
useControl(
() => {
const draw = new MapboxDraw({
modes,
displayControlsDefault: false,
controls: {
polygon: true,
trash: true,
},
});
drawRef.current = draw;
return draw;
},
() => {
mapRef.current.on('draw.create', (e) => {
onCreate(e.features[0]);
});
mapRef.current.on('draw.update', (e) => {
onUpdate(e.features[0]);
});
mapRef.current.on('draw.delete', (e) => {
// Hier muss noch ein Confirm eingebaut werden.
onDelete(e.features.map((feature) => feature.id));
});
mapRef.current.on('draw.selectionchange', (e) => {
const activeFeature = e.features[0];
if (activeFeature) {
onActive(activeFeature?.id);
} else {
onActive('');
clearChangeRange();
}
});
},
() => {
// Cleanup method, if needed
},
{ position: "top-left" }
)
const initItems = useCallback(() => {
mapRef.current.addControl(drawRef.current);
initialData.forEach(item => {
drawRef.current.add(item);
});
// eslint-disable-next-line
}, [])
useEffect(() => {
initItems();
// eslint-disable-next-line
}, [])
return drawRef.current ? <DrawControl drawRef={drawRef} {...child} /> : null;
}
DrawControlContainer.propTypes = {
container: PropTypes.object,
child: PropTypes.object
}
I tried multiple types of Refs and States, multiple useEffects.
I created the control manually and with the useControl hook from mapbox but it's not working :(
Upvotes: 0
Views: 45