Kotlin React项目封装mapbox-gl-draw报错:mapBoxDraw is not a function
Kotlin React项目中mapbox-gl-draw封装报错解决
问题背景
我在Kotlin React项目里封装mapbox-gl-draw,初始写的封装代码如下:
@JsName("default") external fun mapboxDraw()
参考了mapbox-gl-draw的TS类型定义和JS核心源码,但使用时浏览器一直报错“mapBoxDraw is not a function”。最终要实现的是对应下方TS代码的Kotlin JS版本封装:
type DrawControlProps = ConstructorParameters<typeof MapboxDraw>[0] & { position?: ControlPosition; onCreate?: (evt: {features: object[]}) => void; onUpdate?: (evt: {features: object[]; action: string}) => void; onDelete?: (evt: {features: object[]}) => void; }; export default function DrawControl(props: DrawControlProps) { useControl<MapboxDraw>( () => new MapboxDraw(props), ({map}: {map: MapRef}) => { map.on('draw.create', props.onCreate); map.on('draw.update', props.onUpdate); map.on('draw.delete', props.onDelete); }, ({map}: {map: MapRef}) => { map.off('draw.create', props.onCreate); map.off('draw.update', props.onUpdate); map.off('draw.delete', props.onDelete); }, { position: props.position } ); return null; } DrawControl.defaultProps = { onCreate: () => {}, onUpdate: () => {}, onDelete: () => {} };
现在需要先解决封装报错的问题,请问我哪里错了?
错误分析与修正
1. 初始封装的核心错误
mapbox-gl-draw的导出是构造函数,不是普通函数,且你定义的导出名称和结构完全不匹配:
- 源码中mapbox-gl-draw导出的是
MapboxDraw构造函数,而非mapboxDraw或default - 你用
@JsName("default")+external fun的方式,既没正确映射构造函数的类结构,也没匹配库的实际导出名称
2. 正确的基础封装步骤
先修正MapboxDraw的外部类定义,匹配JS库的导出结构:
// 定义MapboxDraw的配置项接口,可根据TS类型补充更多字段 external interface MapboxDrawOptions { var displayControlsDefault: Boolean? var controls: dynamic var defaultMode: String? } // 正确映射JS的MapboxDraw构造函数 @JsModule("@mapbox/mapbox-gl-draw") @JsNonModule external class MapboxDraw(options: MapboxDrawOptions = definedExternally) { // 按需补充需要调用的实例方法,比如getAll()、delete()等 }
3. 对应目标TS代码的完整Kotlin封装
结合Kotlin React的useControl实现和TS版本一致的组件:
import react.FC import react.Props import react.mapgl.useControl // 定义DrawControl的Props,对应TS的DrawControlProps external interface DrawControlProps : MapboxDrawOptions { var position: dynamic? // 对应ControlPosition,如"top-left" var onCreate: ((dynamic) -> Unit)? var onUpdate: ((dynamic) -> Unit)? var onDelete: ((dynamic) -> Unit)? } val DrawControl = FC<DrawControlProps> { props -> // 处理默认回调 val onCreate = props.onCreate ?: { _ -> } val onUpdate = props.onUpdate ?: { _ -> } val onDelete = props.onDelete ?: { _ -> } // 创建并挂载MapboxDraw控件 useControl<MapboxDraw>( create = { MapboxDraw(props) }, onAdd = { context -> val map = context.map map.on("draw.create", onCreate) map.on("draw.update", onUpdate) map.on("draw.delete", onDelete) }, onRemove = { context -> val map = context.map map.off("draw.create", onCreate) map.off("draw.update", onUpdate) map.off("draw.delete", onDelete) }, position = props.position ) // 组件无DOM输出 null } // 设置默认Props fun DrawControlProps.default() { this.onCreate = { _ -> } this.onUpdate = { _ -> } this.onDelete = { _ -> } }
4. 关键注意事项
- 确保已正确安装依赖:
npm install @mapbox/mapbox-gl-draw - 外部类的
@JsModule路径必须匹配npm包的导入路径 - 若需要更类型安全的事件处理,可将
dynamic替换为自定义的DrawEvent接口,比如:external interface DrawEvent { var features: Array<dynamic> var action: String? // 仅onUpdate事件存在 }
内容的提问来源于stack exchange,提问作者Chris Legge
相关产品推荐
相关产品推荐

