点击时在父组件DOM层级外插入组件新实例及参数重复问题求解
问题根源
- 最初直接调用
ReactDOM.render渲染到#CreateArea节点时,每次都会覆盖节点内已有的内容,不会追加新的<CreateLine/>实例 - 后续改用数组存储线条数量的写法,所有
<CreateLine/>渲染时读取的都是当前最新的全局状态值,没有保存每次点击按钮那一刻的参数快照,因此所有实例的参数都完全相同 - 额外用
useEffect+ReactDOM.render手动操作DOM的写法不符合React状态驱动渲染的设计范式,在Next.js SSR场景下还容易出现hydration不匹配的问题
解决方案
完全不需要手动操作DOM,用React原生的状态驱动渲染即可实现需求,核心逻辑是把每次点击时的参数快照存入数组,再直接渲染数组:
- 调整状态定义,改为存储每个线条的参数对象:
// 数组的每个元素对应一个<CreateLine/>的完整参数 const [lines, setLines] = useState([]);
- 调整点击事件,每次点击时把当前的参数快照存入数组:
<AddCircleSharpIcon onClick={() => { setLines([ ...lines, { type, title, line, color, data: [...data] // 拷贝数组避免后续引用变动影响已存参数 } ]) }} />
- 直接在需要渲染线条的位置(对应原
#CreateArea的位置)渲染数组即可:
<div id="CreateArea"> {lines.map((lineProps, index) => ( <CreateLine key={index} // 有业务唯一ID时建议替换为业务ID,性能更优 {...lineProps} /> ))} </div>
如果确实有特殊需求要把组件挂载到React根节点外的DOM节点,建议使用createPortal实现,不要直接调用ReactDOM.render。
内容的提问来源于stack exchange,提问作者Ibra
相关产品推荐
相关产品推荐

