React onClick首次点击无响应,二次点击才触发SVG切换的问题
问题原因及修复方案
核心问题
点击按钮时,你先调用markComplete再执行setIndexTask(i),但React的setState是异步更新的。第一次点击时,markComplete里的indexTask还是旧值,找不到要修改的任务项,状态没变化;第二次点击时,indexTask才更新成上一次的i,此时修改才生效,导致SVG切换延迟一次。
另外还有个潜在问题:let tempList = taskList是直接引用原数组,虽然最后用了[...tempList]更新,但修改原数组违反React状态不可变的原则,可能引发其他意外问题。
修复方案(推荐)
直接把当前任务的索引i传给markComplete,不再依赖indexTask状态,彻底避开异步更新问题,同时遵守状态不可变原则:
const [taskList, setTaskList] = useState([]); // 移除不必要的indexTask、statusTask状态(若SVG组件无需可删除) const markComplete = (index, isComplete) => { // 复制原数组,避免修改原状态 const tempList = [...taskList]; // 直接通过传入的index修改对应任务的状态 tempList[index].status = isComplete; setTaskList(tempList); }
修改渲染部分的点击事件,直接传递当前索引:
{taskList.map((obj, i) => <div key={i} className='div-task'> <div className='div-task-container'> <div className='div-task-status'> <div className='div-task-status-complete' onClick={() => markComplete(i, true)} role={'button'} > <SvgTaskUncomplete statusTask={obj.status}></SvgTaskUncomplete> </div> <div className='div-task-status-uncomplete' onClick={() => markComplete(i, false)} role={'button'} > <SvgTaskComplete statusTask={obj.status}></SvgTaskComplete> </div> </div> </div> </div> )}
额外说明
如果SvgTaskUncomplete和SvgTaskComplete组件需要控制显示逻辑,直接基于obj.status判断即可,不需要额外维护statusTask状态,能简化组件逻辑。
内容的提问来源于stack exchange,提问作者vitalik
相关产品推荐
相关产品推荐

