未使用React Strict Mode时点击函数多次触发、setState偶发为null问题咨询
React点击事件触发两次问题排查与解决方法
排查步骤
排查事件冒泡问题
你当前在onClick回调中仅调用了e.preventDefault(),该方法仅阻止浏览器默认行为(如链接跳转、表单提交),不会阻止事件冒泡。如果div内部子元素(比如<QuestionAndAnswers />组件内的可点击元素)也绑定了点击事件且未阻止冒泡,点击子元素时事件会向上冒泡到父div,导致回调触发两次。
可先在回调中添加e.stopPropagation()验证,若添加后触发次数恢复正常即可确定是冒泡导致。排查重复绑定/重复渲染问题
- 先验证当前组件是否存在不必要的重复渲染:在render函数顶部添加日志,点击后查看是否触发了两次render。若存在重复渲染,大概率是父组件props或当前组件state被意外修改触发重渲染,可借助React DevTools的「高亮重渲染」功能定位触发源。
- 检查是否同时使用了React合成事件和原生DOM事件绑定:若在
componentDidMount等生命周期中用addEventListener给当前div或其父元素绑定过点击事件,又在JSX中声明了onClick,会导致同一个点击动作触发两次回调。
- 排查key值重复问题
你当前map渲染时用question.question_id作为组件key,若questionsAndAnswers数组中存在重复的question_id,React会错误复用DOM节点和事件绑定,点击单个元素时可能触发多个复用节点的绑定事件,表现为回调触发两次,还可能因取到错误的question对象导致setState结果为null。
可临时将key替换为数组索引index测试,若问题消失则说明是key值重复导致,需修复为全局唯一的key值(如后端返回唯一id,或前端拼接${question.question_id}_${index})。
修复方案
- 优化事件回调写法,不要在render中直接写长匿名函数,提取为类方法同时添加冒泡阻止逻辑:
// 类属性箭头函数,不用额外绑定this handleQuestionClick = (questionId, e) => { e.preventDefault(); e.stopPropagation(); // 可添加e.nativeEvent.stopImmediatePropagation()阻止同元素上其他绑定事件执行 console.log("on click event"); // 先校验id合法性,避免setState为null if (!questionId) return; this.setState({ selectedQuestion: questionId }, () => console.log('selected questions1', this.state.selectedQuestion)) }
- JSX中替换原有回调绑定:
<div key={question.question_id} className="col-sm-6 pdg-rgt_0 " onClick={(e) => this.handleQuestionClick(question.question_id, e)} >
- 若验证为key值重复问题,优先修复数组的key为唯一值,不要长期使用索引作为key避免其他渲染异常。
内容的提问来源于stack exchange,提问作者Bhaskar Hs
相关产品推荐
相关产品推荐

