如何为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
相关产品推荐
相关产品推荐

