如何为组件分配ref并传递给子组件?解决ref.current为null问题
问题解决方法
核心问题分析
你直接传ref.current给子组件时,第一次渲染父组件的DOM还未完成挂载,ref.current此时是null——React会在组件挂载完成后的commit阶段才把DOM元素赋值给ref,比渲染阶段晚,所以子组件拿到的target自然为空。
以下是两种可行的解决思路:
思路一:传递ref对象而非ref.current
父组件把整个ref对象传给子组件,子组件在useEffect里监听ref的变化并访问其current属性:
父组件修改:
return ( <div ref={ref} onMouseOver={isSelecting ? handleMouseOver : undefined} onClick={isSelecting ? handleClick : undefined} className='rich-html prose prose-sm dark:prose-invert md:prose-base lg:prose-lg' > {parse(html, options)} <RichHtmlContextMenu targetRef={ref} /> {/* 传递ref对象 */} </div> );
子组件修改:
interface Props { targetRef: React.RefObject<HTMLDivElement>; } const RichHtmlContextMenu = ({ targetRef }: Props) => { useEffect(() => { // 先判断DOM是否已挂载,再执行逻辑 if (targetRef.current) { refs.setReference(targetRef.current.firstChild as HTMLElement); } }, [refs, targetRef]); // ...其他组件逻辑 };
思路二:使用forwardRef时处理类型问题
如果必须用forwardRef,注意ForwardedRef<T>的类型可能是RefObject<T>或赋值函数,需要先判断类型再访问current:
interface Props { // 子组件所需的其他props } const RichHtmlContextMenu = forwardRef<HTMLDivElement, Props>((props, ref) => { useEffect(() => { let targetElement: HTMLElement | null = null; // 区分ref是对象类型还是函数类型 if (typeof ref === 'object' && ref !== null) { targetElement = ref.current?.firstChild as HTMLElement | null; } if (targetElement) { refs.setReference(targetElement); } }, [refs, ref]); // ...其他组件逻辑 });
注意:两种方案都要做好空值判断,避免DOM未挂载时出现报错。
内容的提问来源于stack exchange,提问作者Ugus
相关产品推荐
相关产品推荐

