React中如何将GridItem的ref作为prop传递给对象内存储的组件?
你之前实现失败的核心原因是 availableWidgets 中存储的是已经实例化完成的React元素(比如 <DashboardsGuide /> 是已经调用渲染后的结果),无法再给这类预渲染的元素追加props或ref。按照下面的方案修改即可实现需求:
第一步:重构availableWidgets结构
把存储预渲染元素改为存储组件本身,方便后续动态传参:
const availableWidgets = [ {}, { component: DashboardsGuide, // 去掉< />,存组件引用 id: "1" }, { component: DashboardsWeather, id: "2" }, { component: DashboardsTraining, id: "3" }, ];
第二步:选择合适的传值方案
根据你的需求可以选以下三种方案中的任意一种:
方案1:普通prop传递ref(最简方案,无需修改子组件定义)
直接把GridItem的ref作为普通prop传给子组件,不需要用forwardRef包裹子组件:
const GridItem = React.forwardRef(function GridItem( { className, style, children, item, widget, id, ...rest }, ref ) { return ( <div id={`width-height-${id}`} className={`grid-item ${className}`} style={style} ref={ref} {...rest} > {/* 动态渲染组件,把ref作为普通prop传入 */} {widget?.component && <widget.component gridItemRef={ref} />} {children} </div> ); });
子组件中直接通过props访问即可,注意要在useEffect里读取ref.current(保证DOM已经挂载):
// 子组件示例 function DashboardsGuide({ gridItemRef }) { useEffect(() => { if (gridItemRef.current) { console.log("GridItem宽度:", gridItemRef.current.offsetWidth); console.log("GridItem高度:", gridItemRef.current.offsetHeight); } }, [gridItemRef]); return <div>组件内容</div> }
方案2:符合React规范的ref传递(用forwardRef)
如果需要遵循React的ref传递规范,可以用forwardRef包裹所有widget子组件:
// 子组件用forwardRef包裹 const DashboardsGuide = React.forwardRef((props, ref) => { useEffect(() => { if (ref.current) { console.log("GridItem宽度:", ref.current.offsetWidth); } }, [ref]); return <div>组件内容</div> });
GridItem中直接把ref传给子组件即可:
{widget?.component && <widget.component ref={ref} />}
方案3:仅传递宽高(更安全,无需暴露完整DOM节点)
如果子组件只需要GridItem的尺寸信息,不需要完整DOM引用,可以直接监听尺寸变化后传宽高值:
const GridItem = React.forwardRef(function GridItem( { className, style, children, item, widget, id, ...rest }, ref ) { const [gridSize, setGridSize] = useState({ width: 0, height: 0 }); useEffect(() => { if (!ref.current) return; // 初始化尺寸 const updateSize = () => { setGridSize({ width: ref.current.offsetWidth, height: ref.current.offsetHeight }); }; updateSize(); // 监听GridItem尺寸变化(拖拽/缩放时自动更新) const resizeObserver = new ResizeObserver(updateSize); resizeObserver.observe(ref.current); return () => resizeObserver.disconnect(); }, [ref]); return ( <div id={`width-height-${id}`} className={`grid-item ${className}`} style={style} ref={ref} {...rest} > {widget?.component && <widget.component gridSize={gridSize} />} {children} </div> ); });
子组件直接读取props.gridSize即可拿到实时宽高,无需处理ref判断。
内容的提问来源于stack exchange,提问作者Harsh Mendapara
相关产品推荐
相关产品推荐

