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

如何为forwardRef包裹的组件使用react-error-boundary并保留ref转发、新增props

实现方式

不需要改动原有MapWithoutErrorBoundary组件的代码,在外层包裹时额外套一层forwardRef做ref透传,同时通过类型交叉合并新增自定义属性的类型,渲染时拆分props分别传给ErrorBoundary和内部原地图组件即可。

完整实现代码

import React, { forwardRef, useRef } from 'react';
import mapboxgl from 'mapboxgl';
import { ErrorBoundary } from '@/components/ErrorBoundary'; // 替换成你项目里ErrorBoundary的实际引入路径
import { MapWithoutErrorBoundary, MapWithoutErrorBoundaryProps } from './原地图组件路径';

// 1. 定义你需要新增的自定义属性类型,按需增减字段即可
type WrappedMapExtraProps = {
  /** 地图组件报错时的降级展示UI */
  errorFallback?: React.ReactNode;
  /** 地图组件抛出错误时的回调 */
  onMapCatch?: (error: Error, errorInfo: React.ErrorInfo) => void;
}

// 2. 合并原组件Props和新增自定义Props,作为包裹后组件的属性类型
type MapWithErrorBoundaryProps = MapWithoutErrorBoundaryProps & WrappedMapExtraProps;

// 3. 包裹后的组件同样使用forwardRef,ref泛型和原组件保持一致,保证拿到的实例类型正确
export const Map = forwardRef<mapboxgl.Map | null, MapWithErrorBoundaryProps>(
  (props, ref) => {
    // 4. 拆分props:把ErrorBoundary用到的自定义属性拆出来,剩余属性全部透传给原地图组件
    const { errorFallback, onMapCatch, ...restMapProps } = props;

    return (
      <ErrorBoundary
        fallback={errorFallback}
        onError={onMapCatch}
      >
        {/* 关键:ref直接透传给原地图组件,不要挂在ErrorBoundary上 */}
        <MapWithoutErrorBoundary ref={ref} {...restMapProps} />
      </ErrorBoundary>
    );
  }
);

// 可选:配置displayName方便React DevTools调试
Map.displayName = 'MapWithErrorBoundary';

关键注意点

  • ref必须直接透传给内层的MapWithoutErrorBoundary,ErrorBoundary作为错误捕获容器本身不需要接收这个ref,否则拿不到正确的mapbox地图实例
  • 新增的自定义属性必须在外层拆分干净,不要把ErrorBoundary专属的属性透传给原地图组件,避免触发React无效属性警告
  • 如果你的ErrorBoundary组件接收的props名和示例不一致(比如用FallbackComponent、fallbackRender替代fallback),对应调整传参即可,不影响核心逻辑

使用示例

包裹后的组件和原组件用法完全一致,ref转发正常生效,同时支持新增的自定义属性:

const MapPage = () => {
  const mapInstanceRef = useRef<mapboxgl.Map | null>(null);

  const handleMapReady = () => {
    // 可以正常拿到mapbox实例,ref转发无感知
    console.log('地图实例:', mapInstanceRef.current);
  };

  return (
    <Map
      ref={mapInstanceRef}
      {/* 原组件属性正常传递 */}
      style={{ width: '100%', height: '70vh' }}
      initialCenter={[116.397428, 39.90923]}
      initialZoom={12}
      onReady={handleMapReady}
      {/* 新增的自定义属性正常传递 */}
      errorFallback={<div className="error-tip">地图加载失败,请刷新页面重试</div>}
      onMapCatch={(err) => {
        console.error('地图运行报错:', err);
        // 这里可以加埋点上报逻辑
      }}
    />
  );
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 01:57:11