React中向DOM添加元素需两次点击而非一次的问题如何解决?
问题原因
- 事件冒泡:添加按钮位于绑定了点击事件的
.utility父容器内部,点击按钮时事件会向上冒泡触发父容器的showIcon回调,单次点击同时执行两个逻辑,导致状态更新异常,表现为需要点击两次才能生效。 - 不合理的State用法:直接将React组件实例存储在State中,不符合React设计规范,容易触发闭包陷阱,导致回调函数获取到旧的状态值。
修复方案
- 点击添加按钮时调用
e.stopPropagation()阻止事件冒泡,避免触发父容器的点击回调 - 调整State结构,使用布尔值控制添加按钮的显隐,不要在State中存储JSX元素
- 更新列表状态时使用函数式写法,避免闭包导致的旧状态依赖问题
修正后代码
import React, {useState} from 'react' import StabelItem from './StabelItem'; import { library } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faPlusCircle} from '@fortawesome/free-solid-svg-icons'; library.add(faPlusCircle) // React组件名需首字母大写 function AddItems() { // 用布尔值控制图标显隐 const [showAddIcon, setShowAddIcon] = useState(false); const [stabelItem, setStabelItem] = useState({items:[]}); const showIcon = ()=> { setShowAddIcon(true) } const addStabelItem = (e) => { // 阻止事件冒泡 e.stopPropagation(); // 函数式更新避免闭包问题 setStabelItem(prev => ({items: [...prev.items, <StabelItem />]})) } return ( <div className="utility" onClick={showIcon}> <li className="box-item" > <div className="flexrow" > <div className='number norest'>Total</div> <div className='number calc margin-left norest'>0</div> </div> <ul className="movements"> {stabelItem.items} {/* 条件渲染图标 */} {showAddIcon && <FontAwesomeIcon onClick={addStabelItem} icon={["fas", "plus-circle"]}/>} </ul> </li> </div> ) }
内容的提问来源于stack exchange,提问作者Richardson
相关产品推荐
相关产品推荐

