如何创建带ref的React元素并追加到仅能获取ref的封装父组件中
报错核心原因
React.createElement() 返回的是React虚拟DOM对象,不是浏览器原生的Node类型真实DOM节点,而原生appendChild方法只接受真实DOM作为参数,所以出现类型不匹配报错。
可行修复方案
方案1:使用React Portal实现(推荐,符合React渲染逻辑)
Portal可以直接把React元素渲染到指定的真实DOM节点下,同时完全支持React的ref绑定机制,不需要手动操作DOM:
import { createPortal } from 'react-dom'; const Demo: React.FC = () => { const parentRef = useRef<HTMLElement>(null); const childRef = useRef<HTMLElement>(null); const [isParentMounted, setIsParentMounted] = useState(false); useEffect(() =>{ if(parentRef.current) { setIsParentMounted(true); } },[]) return ( <> <Parent ref={parentRef} {...allprops} /> {isParentMounted && createPortal( <div ref={childRef}></div>, parentRef.current! )} </> ) }; export default Demo;
该方案下子元素的更新、卸载都由React自动管控,不需要额外处理副作用。
方案2:原生创建DOM手动绑定ref
如果必须用原生appendChild实现,可以原生创建DOM节点后直接给ref赋值即可,React的ref本身支持存储任意可变值:
const Demo: React.FC = () => { const parentRef = useRef<HTMLElement>(null); const childRef = useRef<HTMLElement>(null); useEffect(() =>{ if(parentRef.current) { const child = document.createElement("div"); // 直接给ref赋值完成绑定 childRef.current = child; parentRef.current.appendChild(child); } // 卸载时手动清理节点避免内存泄漏 return () => { childRef.current?.remove(); } },[]) return ( <> <Parent ref={parentRef} {...allprops} /> </> ) }; export default Demo;
注意该方案下创建的DOM不在React管控范围内,属性更新、事件绑定都需要手动操作。
内容的提问来源于stack exchange,提问作者clothoGo
相关产品推荐
相关产品推荐

