这不是 Mapbox 相关问题,您不需要任何地图或相关知识来帮助。我的问题与 React refs 有关。
我正在使用
react-map-gl
(React 的 Mapbox)和 @mapbox/mapbox-gl-draw
,允许用户在地图上绘制几何图形。该应用程序有 2 个组件:DrawControl
,用于公开绘制功能;AllPastures
,用于渲染地图并管理创建/更新/删除绘制的几何图形。
当用户绘制多边形时,它会触发执行
DrawControl
的 onCreate
方法 onCreateOrUpdate
。我正在通过 forwardRef
从 DrawControl
到 AllPastures
进行抽奖。
这是一个
DrawControl
组件:
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;
}
这是
AllPastures
组件的一部分:
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}
/>
);
};
我的问题是,发现为什么当方法
onCreateOrUpdate
drawRef
未定义时?
这是一个模拟该问题的相关沙箱: https://stackblitz.com/edit/vitejs-vite-bvutvb?file=src%2FAllPastures.tsx
只需在地图上绘制任何多边形并检查console.log
drawRef under onCreateOrUpdate method
未定义。
请更改代码后,按F5完成刷新页面并再次测试。
const onCreateOrUpdate = React.useCallback((e: { features: Feature[] }) => {
// Here drawRef would not be undefined
console.log('drawRef under onCreateOrUpdate method', drawRef);
}, [drawRef]);
对于其他正在寻找解决方案的人,我找到了一种使用
drawRef
、DrawControl
将 forwardRef
转发到 useImperativeHandle
之外的方法,并将该引用附加到我的 <DrawControl>
。
下面的工作示例以及完整的解决方案:https://stackblitz.com/edit/vitejs-vite-bvutvb?file=src%2FDraw.tsx
export const Draw = () => {
const { current: map } = useMap();
const [drawMode, setDrawMode] = React.useState<DrawMode>('simple_select');
const drawRef = React.useRef<MapboxDraw>(null);
if (!map) {
return null;
}
React.useEffect(() => {
// it's ok here, drawRef is not undefined
console.log('useEffect drawRef when app is loading', drawRef);
}, [drawRef]);
const onCreateOrUpdate = React.useCallback(
(e: { features: Feature[] }) => {
// Here drawRef would not be undefined
console.log('drawRef under onCreateOrUpdate method', drawRef);
},
[drawRef]
);
return (
<DrawControl
ref={drawRef}
position="top-right"
displayControlsDefault={false}
controls={{
polygon: true,
trash: true,
}}
defaultMode="simple_select"
modes={{ ...MapboxDraw.modes, draw_rectangle: DrawRectangle }}
onCreate={onCreateOrUpdate}
onUpdate={onCreateOrUpdate}
/>
);
};