React如何实现点击按钮时向body重复追加自定义div组件?
解决方案
问题原因
你写的AppendHtml只是一个返回Portal元素的普通函数,直接调用它只会生成React虚拟元素,没有触发React的渲染流程,自然不会生成真实DOM插入到body中。只有把它放到组件的JSX返回值里时,React才会处理这个Portal元素,将对应的内容渲染到body上。
实现代码
React 18 版本
import { createRoot } from 'react-dom/client' // 你要追加的组件 const MyEl = () => { return <div>Hello</div> } export const MyComponent = () => { const buttonClick = () => { // 1. 创建临时容器节点 const container = document.createElement('div') // 2. 把容器追加到body document.body.appendChild(container) // 3. 把MyEl渲染到这个容器中 const root = createRoot(container) root.render(<MyEl />) } return ( <button onClick={buttonClick}>Click Me!</button> ) }
React 17 及更早版本
import ReactDOM from 'react-dom' const MyEl = () => { return <div>Hello</div> } export const MyComponent = () => { const buttonClick = () => { const container = document.createElement('div') document.body.appendChild(container) ReactDOM.render(<MyEl />, container) } return ( <button onClick={buttonClick}>Click Me!</button> ) }
扩展功能(可选)
如果后续需要卸载这些动态追加的组件,可以把实例和容器存到ref中,需要的时候统一清理:
import { useRef } from 'react' import { createRoot } from 'react-dom/client' const MyEl = () => { return <div>Hello</div> } export const MyComponent = () => { // 存储所有动态生成的实例 const dynamicInstances = useRef([]) const buttonClick = () => { const container = document.createElement('div') document.body.appendChild(container) const root = createRoot(container) root.render(<MyEl />) dynamicInstances.current.push({ root, container }) } // 清理所有追加的元素 const clearAll = () => { dynamicInstances.current.forEach(({ root, container }) => { root.unmount() container.remove() }) dynamicInstances.current = [] } return ( <> <button onClick={buttonClick}>点击追加</button> <button onClick={clearAll}>清空所有</button> </> ) }
注意事项
这种手动渲染的组件默认不在你原有应用的React上下文树中,如果MyEl需要用到全局Context(比如Redux、主题配置等),需要在渲染时手动把对应的Provider包在MyEl外层。
内容的提问来源于stack exchange,提问作者code0x00
相关产品推荐
相关产品推荐

