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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 08:25:20