React使用cloneElement复制DOM节点报元素类型无效错误如何解决?
错误触发原因
- 你混淆了原生DOM节点和React虚拟元素的概念:
document.querySelector('.items_wrapper')返回的是浏览器原生DOM对象,而React.cloneElement的入参要求是React创建的虚拟元素对象(即JSX语法编译后生成的对象),两者类型完全不匹配。React读取元素类型时会尝试获取虚拟元素的type字段,原生DOM节点不存在该字段,返回undefined,就触发了你看到的类型无效报错。 - 直接通过原生DOM API操作React渲染的节点属于违规写法:React内部维护了独立的虚拟DOM树,你手动追加的真实DOM不在React的管控范围内,后续价格等状态更新时,手动添加的节点不会同步更新,还可能引发渲染冲突、内存泄漏等问题。
解决方案
遵循React的声明式渲染逻辑,不要手动操作DOM,改写法如下:
- 第一步:将滚动列表的内容抽成独立组件,避免重复编写JSX
// 抽离公共的列表项组件 const CryptobarItems = ({ btc_price, cardan_price, dogecoin_price, eth_price, bnb_price, btc_icon, cardano_icon, dogecoin_Logo, eth_icon, bnb_icon }) => { return ( <div className={'items_wrapper'}> <div className={'cryptobar_item'}> <img src={btc_icon} alt={'btc_icon'}/> <p>{btc_price} $</p> </div> <div className={'cryptobar_item'}> <img src={cardano_icon} alt={'cardano_icon'}/> <p>{cardan_price} $</p> </div> <div className={'cryptobar_item'}> <img src={dogecoin_Logo} alt={'dogecoin_icon'}/> <p>{dogecoin_price} $</p> </div> <div className={'cryptobar_item'}> <img src={eth_icon} alt={'eth_icon'}/> <p>{eth_price} $</p> </div> <div className={'cryptobar_item'}> <img src={bnb_icon} alt={'bnb_icon'}/> <p>{bnb_price} $</p> </div> <div className={'cryptobar_item'}> <img src={bnb_icon} alt={'bnb_icon'}/> <p>{bnb_price} $</p> </div> </div> ) }
- 第二步:在原来的容器中直接渲染两次该组件即可,不需要手动操作DOM
<div className={'cryptobar_wrapper'}> <CryptobarItems btc_price={btc_price} cardan_price={cardan_price} dogecoin_price={dogecoin_price} eth_price={eth_price} bnb_price={bnb_price} btc_icon={btc_icon} cardano_icon={cardano_icon} dogecoin_Logo={dogecoin_Logo} eth_icon={eth_icon} bnb_icon={bnb_icon} /> {/* 直接渲染第二份,自动追加到容器内,状态和第一份完全同步 */} <CryptobarItems btc_price={btc_price} cardan_price={cardan_price} dogecoin_price={dogecoin_price} eth_price={eth_price} bnb_price={bnb_price} btc_icon={btc_icon} cardano_icon={cardano_icon} dogecoin_Logo={dogecoin_Logo} eth_icon={eth_icon} bnb_icon={bnb_icon} /> </div>
如果需要做无缝滚动效果,只需要给外层cryptobar_wrapper加overflow-x: hidden,再给内层两个items_wrapper配置flex或者浮动布局,配合CSS动画实现滚动即可,所有逻辑完全符合React规范,不会出现状态不同步的问题。
内容的提问来源于stack exchange,提问作者Kadiem Alqazzaz
相关产品推荐
相关产品推荐

