You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在TypeScript React中向Nebula.gl HTMLClusterOverlay传数据的问题

问题

在基于TypeScript的React(搭配Deck.gl)项目中添加地图聚类功能,选用Nebula.gl的HtmlClusterOverlay组件实现。参考官方示例通过<ClusterLayer data={data} />传递GeoJSON的Feature数组时,出现类型错误,提示'data'属性不存在于ClusterLayer的props类型中。已自定义继承HtmlClusterOverlay的ClusterLayer子类,想知道能否为该子类添加自定义属性,或者有没有更优的数据传递方式。

错误信息如下:

No overload matches this call.
  Overload 1 of 2, '(props: Readonly<{ viewport?: Record<string, any> | undefined; zIndex?: number | undefined; children?: ReactNode; }>): ClusterLayer', gave the following error.
    Type '{ data: Feature[] | undefined; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<ClusterLayer> & Readonly<{ viewport?: Record<string, any> | undefined; zIndex?: number | undefined; children?: ReactNode; }> & Readonly<...>'.
      Property 'data' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<ClusterLayer> & Readonly<{ viewport?: Record<string, any> | undefined; zIndex?: number | undefined; children?: ReactNode; }> & Readonly<...>'.
  Overload 2 of 2, '(props: { viewport?: Record<string, any> | undefined; zIndex?: number | undefined; children?: ReactNode; }, context?: any): ClusterLayer', gave the following error.
    Type '{ data: Feature[] | undefined; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<ClusterLayer> & Readonly<{ viewport?: Record<string, any> | undefined; zIndex?: number | undefined; children?: ReactNode; }> & Readonly<...>'.
      Property 'data' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<ClusterLayer> & Readonly<{ viewport?: Record<string, any> | undefined; zIndex?: number | undefined; children?: ReactNode; }> & Readonly<...>'.

自定义子类代码:

class ClusterLayer extends HtmlClusterOverlay<Feature> {

    getAllObjects() {
        return this.props.data;
    }

    getObjectCoordinates(object: Feature) {
        const lat: number = object.geometry.coordinates[0];
        const long: number = object.geometry.coordinates[1];
        return [lat, long] as [number, number];
    }

    renderObject(coordinates: [number, number], object: Feature) {
        if (this.getZoom() > 5) {
            return (
                <HtmlOverlayItem
                    style={{
                        background: 'red',
                        padding: 4,
                        color: 'white',
                        fontSize: 12,
                        lineHeight: '10px',
                        maxWidth: 300
                    }}
                    key={object.properties.name}
                    coordinates={coordinates}
                >
                    {Object}
                </HtmlOverlayItem>
            );
        }

        return (
            <HtmlOverlayItem
                style={{ background: 'red', padding: 4 }}
                key={object.properties.name}
                coordinates={coordinates}
            >

            </HtmlOverlayItem>
        );
    }

    renderCluster(coordinates: [number, number], clusterId: React.Key | undefined, pointCount: any) {
        return (
            <HtmlOverlayItem
                style={{
                    background: 'blue',
                    padding: 4,
                    color: 'white',
                    width: 40,
                    height: 40,
                    borderRadius: 20,
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center'
                }}
                key={clusterId}
                coordinates={coordinates}
            >
                {pointCount}
            </HtmlOverlayItem>
        );
    }
}
解决方案

1. 为子类扩展Props类型

TypeScript报错的核心是ClusterLayer的Props类型未包含data字段,需要自定义Props接口,继承HtmlClusterOverlay的原有Props并添加data属性:

import { HtmlClusterOverlayProps } from 'nebula.gl';
import { Feature } from 'geojson';

// 自定义Props接口,继承原有Props并添加data字段
interface ClusterLayerProps extends HtmlClusterOverlayProps<Feature> {
  data: Feature[] | undefined;
}

2. 修改子类定义,使用自定义Props

更新ClusterLayer类的定义,指定Props类型为自定义的ClusterLayerProps:

class ClusterLayer extends HtmlClusterOverlay<Feature, ClusterLayerProps> {
  // 类方法保持不变,此时this.props.data会被TypeScript正确识别
  getAllObjects() {
    return this.props.data;
  }

  // ... 其余方法代码不变
}

3. 可选:改用函数组件实现(更符合React现代写法)

如果项目允许,推荐用函数组件结合useHtmlClusterOverlay钩子实现,类型定义更简洁:

import { useHtmlClusterOverlay, HtmlOverlayItem } from 'nebula.gl';
import { Feature } from 'geojson';

interface ClusterLayerProps {
  data: Feature[] | undefined;
  viewport?: Record<string, any>;
  zIndex?: number;
}

const ClusterLayer = ({ data, viewport, zIndex }: ClusterLayerProps) => {
  const { getZoom } = useHtmlClusterOverlay({
    viewport,
    zIndex,
    getAllObjects: () => data,
    getObjectCoordinates: (object: Feature) => {
      const [lat, long] = object.geometry.coordinates;
      return [lat, long] as [number, number];
    },
    renderObject: (coordinates, object) => {
      if (getZoom() > 5) {
        return (
          <HtmlOverlayItem
            style={{
              background: 'red',
              padding: 4,
              color: 'white',
              fontSize: 12,
              lineHeight: '10px',
              maxWidth: 300
            }}
            key={object.properties.name}
            coordinates={coordinates}
          >
            {object.properties.name}
          </HtmlOverlayItem>
        );
      }
      return (
        <HtmlOverlayItem
          style={{ background: 'red', padding: 4 }}
          key={object.properties.name}
          coordinates={coordinates}
        />
      );
    },
    renderCluster: (coordinates, clusterId, pointCount) => {
      return (
        <HtmlOverlayItem
          style={{
            background: 'blue',
            padding: 4,
            color: 'white',
            width: 40,
            height: 40,
            borderRadius: 20,
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center'
          }}
          key={clusterId}
          coordinates={coordinates}
        >
          {pointCount}
        </HtmlOverlayItem>
      );
    }
  });

  return null; // useHtmlClusterOverlay会自动渲染overlay内容
};

4. 注意事项

  • 原代码中renderObject里的{Object}是错误写法,应该替换为具体的Feature属性(比如object.properties.name)
  • 确保Feature类型正确导入(通常来自geojson包)

内容的提问来源于stack exchange,提问作者strange_noise

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 14:36:20