You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 17:42:01