This is not a Mapbox related issue, and you don’t need any map or related stuff knowledge to help. My issue is related to React refs.
I’m using react-map-gl
(Mapbox for React) with @mapbox/mapbox-gl-draw
that allow user to draw geometries on the map. This app has 2 components: DrawControl
that exposes draw features and AllPastures
that renders the map and manage create/update/delete geometries drawed.
When user draws a polygon it fires the DrawControl
method onCreate
that executes onCreateOrUpdate
. I’m passing the Draw by forwardRef
from DrawControl
to AllPastures
.
This is a DrawControl
component:
export const DrawControl = React.forwardRef<MapboxDraw, DrawControlProps>(
(props: DrawControlProps, ref) => {
const drawRef: MapboxDraw = useControl<MapboxDraw>(
() => new MapboxDraw(props),
({ map }) => {
map.on('draw.create', props.onCreate);
map.on('draw.update', props.onUpdate);
map.on('draw.delete', props.onDelete);
map.on('draw.modechange', props.onModeChange);
},
({ map }) => {
map.off('draw.create', props.onCreate);
map.off('draw.update', props.onUpdate);
map.off('draw.delete', props.onDelete);
map.off('draw.modechange', props.onModeChange);
},
{
position: props.position,
}
);
// exposing drawRef outside the component by Ref
React.useImperativeHandle(ref, () => drawRef, [drawRef]);
return null;
}
and this is part of AllPastures
component:
export const AllPastures = () => {
...
const [drawRef, setDrawRef] = React.useState<MapboxDraw>();
// here I’m using callback ref to react to drawRef changes
const onDrawRef = React.useCallback((ref: MapboxDraw | null) => {
if (ref) {
setDrawRef(ref);
}
}, []);
React.useEffect(() => {
// it's ok here, drawRef is not undefined
console.log('useEffect drawRef when app is loading', drawRef);
}, [map, drawRef]);
const onCreateOrUpdate = (e: { features: Feature[] }) => {
// Why drawRef is undefined here????????????????????
console.log('drawRef under onCreateOrUpdate method', drawRef);
};
...
return (
<DrawControl
ref={onDrawRef}
position="top-right"
displayControlsDefault={false}
controls={{
polygon: true,
trash: true,
}}
defaultMode="simple_select"
onCreate={onCreateOrUpdate}
onUpdate={onCreateOrUpdate}
/>
);
};
My issue is, discover why when the the method onCreateOrUpdate
the drawRef
is undefined?
Here is a related sandbox simulating the issue: https://stackblitz.com/edit/vitejs-vite-bvutvb?file=src%2FAllPastures.tsx
Just draw any polygon on the map and check the console.log drawRef under onCreateOrUpdate method
is undefined.
Please, after make changes in the code, do a F5 to complete refresh the page and test it again.
For someone else is looking for a solution, I found a way forwarding the
drawRef
outside theDrawControl
usingforwardRef
,useImperativeHandle
and attaching that ref to my<DrawControl>
.The working example bellow, and a complete solution on: https://stackblitz.com/edit/vitejs-vite-bvutvb?file=src%2FDraw.tsx