反应,为啥标签不为复选框触发 onChange?
Posted
技术标签:
【中文标题】反应,为啥标签不为复选框触发 onChange?【英文标题】:React, Why label not firing onChange for checkbox?反应,为什么标签不为复选框触发 onChange? 【发布时间】:2018-04-10 03:42:02 【问题描述】:我觉得我已经做过一百万次了,但可能没有使用映射功能。我有一组活动,我正在创建复选框,代码如下(顺便说一下,__map
来自 Lodash):
<div className="activity-blocks">
__map(this.state.activities, (activity, i) =>
return (
<div key= i className="single-activity">
<input id= `register-activity-$ i `
type="checkbox" className="register-multiselect"
name="main_activity" checked= !!activity.checked
onChange= (e) => this.toggleActivity(e, activity.id)
/>
<label htmlFor= `register-activity-$ i ` > activity.name </label>
</div>
)
)
我的onChange
处理程序如下所示:
toggleActivity(e, activityId)
let activities = ...this.state.activities ;
__forEach(this.state.activities, (activity) =>
if (activityId === activity.id)
activity = __assign(activity, checked: e.target.checked );
return false;
);
this.setState( activities: activities );
处理程序工作得很好,主要是供参考。我的问题是标签没有触发处理程序。我只测试了没有标签的复选框输入,它触发了处理程序。有谁知道为什么标签不这样做?
更多信息:我以前遇到过这个问题,但通常结果是 id 不匹配或类似的简单问题。这次我不相信。
编辑 我已经从我的文件中删除了几乎所有的代码,并在下面合并了 Slawa 的答案,但它仍然没有按预期运行。这是包含所有导入、类结构和所有不必要的代码的代码,包括样式:
import React from 'react';
import __forEach from 'lodash/forEach';
import __assign from 'lodash/assign';
import __map from 'lodash/map';
export default class RegisterActivities extends React.Component
constructor(props)
super(props);
this.state =
activities: [
id: 1,
name: 'label-1'
,
id: 2,
name: 'label-2'
,
id: 3,
name: 'label-3'
],
toggleActivity(e, activityId)
const activities = this.state;
const updated = activities.map((activity) =>
if (activity.id === activityId)
return
...activity,
checked: e.target.checked
return activity;
);
render()
return (
<div>
<p>what do you do?</p>
<div>
__map(this.state.activities, (activity, i) =>
return (
<div key= i >
<input id= `register-activity-$ i `
type="checkbox"
name="main_activity" checked= !!activity.checked
onChange= (e) => this.toggleActivity(e, activity.id)
/>
<label htmlFor= `register-activity-$ i ` > activity.name </label>
</div>
)
)
</div>
</div>
);
编辑2
我在玩,决定用onClick
替换onChange
,现在我可以点击实际的复选框来点击toggleActivity
。有人知道为什么 onChange 没有触发吗?
【问题讨论】:
【参考方案1】:找到了我的问题的答案on this SO post。事实证明,我的标签的 onClick
事件(在 html/React 的幕后,不是我自己编码的)正在冒泡到父级而不是处理输入。我需要通过 onClick= e => e.stopPropagation()
告诉标签停止传播。
【讨论】:
好吧,你忽略了 React 对复选框更改的处理实际上是基于点击的 hack,“以规范浏览器差异”,所以如果你有任何无害点击preventDefault
的祖先,它干扰 React 的复选框更改黑客。【参考方案2】:
我认为,您的 toggleActivity 函数有错误,活动是数组并尝试将其转换为对象,您可以在这里找到我的完整解决方案:https://codesandbox.io/s/wqyolw50vl
toggleActivity(e, activityId)
const activities = this.state;
const updated = activities.map( activity =>
if (activity.id === activityId)
return
...activity,
checked: !activity.checked
return activity;
)
this.setState( activities: updated );
【讨论】:
感谢您的收获。出于某种原因,我仍然无法弄清楚是什么阻止了我的标签单击输入。toggleActivity
根本不会触发。将调试器放在函数的顶部不会做任何事情。
在您的示例中,您没有正确更新本地状态,因此您的复选框没有新的选中值,codesandbox.io/s/wqyolw50vl - 工作示例
我刚刚在我的文件中使用您的示例进行了编辑,删除了所有其他代码,但它仍然不适合我。 编辑同样出于绝望,我将您在 App 类中的解决方案完全复制到我的解决方案中,但仍然没有触发任何点击。【参考方案3】:
我遇到了同样的问题。这让我发疯,但我和我的团队发现他们告诉你在文档中使用的htmlFor
一定有一些错误。我们从我们的复选框属性中删除了它,现在它按预期运行,没有奇怪的副作用。我正在打开一个GH问题。稍后我将使用链接/更新进行编辑
无效的代码:
<label htmlFor=`$label-checkbox` className=checked ? "checked data-filter-checkbox" : "data-filter-checkbox" >
<input id=`$label-checkbox` type="checkbox" onChange=(event) => handleCheck(event) value=label name=label checked=checked />
label
<span>count</span>
</label>
我现在使用的代码:
<label className=checked ? "checked data-filter-checkbox" : "data-filter-checkbox" >
<input id=`$label-checkbox` type="checkbox" onChange=(event) => handleCheck(event) value=label name=label checked=checked />
label
<span>count</span>
</label>
【讨论】:
太棒了。我正在处理的项目是唯一需要动态创建复选框的项目,所以我很想知道它的进展。谁知道呢,也许这只是 React 15 的错误,在 16 中修复了。以上是关于反应,为啥标签不为复选框触发 onChange?的主要内容,如果未能解决你的问题,请参考以下文章