Javascript 为什么ReactJS处理radio`checked`attr与其他attr不同?
tl;drReact拒绝在输入上执行Javascript 为什么ReactJS处理radio`checked`attr与其他attr不同?,javascript,forms,reactjs,Javascript,Forms,Reactjs,tl;drReact拒绝在输入上执行checked={checkthispoption},即使它在同一组输入上完全执行data ischecked={checkthispoption} 我还没有在jsfiddle上完成这项工作,但是我已经用jsfiddle复制了这个问题 长版本 我有一个简单的ReactJS组件,它向用户显示单选按钮列表。用户应该能够选择一台收音机,然后按下按钮确认他们的选择 以下是组件def(注意:我使用的是ES6和webpack): 从“React”导入React; 类小部件
checked={checkthispoption}
,即使它在同一组输入上完全执行data ischecked={checkthispoption}
我还没有在jsfiddle上完成这项工作,但是我已经用jsfiddle复制了这个问题
长版本
我有一个简单的ReactJS组件,它向用户显示单选按钮列表。用户应该能够选择一台收音机,然后按下按钮确认他们的选择
以下是组件def(注意:我使用的是ES6和webpack):
从“React”导入React;
类小部件扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
currentValue:null//按其值跟踪当前选定的选项
};
}
onClickOptionRadio=(事件)=>{
这是我的国家({
currentValue:String(event.currentTarget.value)
});
}
onConfirm=(事件)=>{
如果(!this.props.onChange)返回;
this.props.onChange(this.state.currentValue);
};
render(){
让选择=this.props.choices;
让currentValue=this.state.currentValue;
返回(
{
choices.map((choice,i)=>{
//决定是否将收音机标记为已选中:
//-如果当前没有选择,请检查第一台收音机
//-否则,请检查与当前选择匹配的无线电
设noCurrentChoice=(currentValue==null);
设drawingFirstChoice=(i==0);
让ThisChoicesSelected=(字符串(choice.value)==currentValue);
让我们选中ThisOption=ThisChoicesSelected | | |(noCurrentChoice&&drawingFirstChoice);
返回(
{choice.label}
{' '}
{checkThisOption?'CHECKED':'''}
);
})
}
确认选择
);
}
}
导出默认窗口小部件;
以下是所属组件:
import React from 'react';
import Widget from 'components/widget';
class Owner extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
let choices = [
{ value: 10, label: 'First' },
{ value: 20, label: 'Second' },
{ value: 30, label: 'Third' }
];
return (
<div className="Owner">
<Widget
choices={choices}
/>
</div>
);
}
}
export default Owner;
从“React”导入React;
从“组件/小部件”导入小部件;
类所有者扩展了React.Component{
建造师(道具){
超级(道具);
this.state={};
}
render(){
让选择=[
{value:10,标签:'First'},
{value:20,标签:'Second'},
{值:30,标签:'Third'}
];
返回(
);
}
}
导出默认所有者;
下面是一个正在运行的gif:
请注意视频中的几点:
- 该逻辑显然适用于在初始渲染时检查第一个收音机
- 当用户单击其他收音机时,它们不会被选中
- 但是,该逻辑明确用于识别所选项目,如收音机上应检查的
所示右侧边距:2rem
- 指示选择了哪个选项的文本始终是准确的
- 当我单击收音机时,
方法;它的祖先都没有更新组件将仅为小部件本身触发update
小部件
实例不会被状态为空的不同实例替换。输入上的data-
attr以及纯文本准确地反映了当前选择,这表明状态正在按预期持续。我确信这种不受欢迎的行为是设计出来的,我想知道如何处理应用于受控输入的表单相关属性的奇怪、异常的逻辑
为什么我认为当前的行为是错误的?我不希望拥有的组件知道每一次无线电点击——所有者应该绑定到小部件的onChange
方法,以便在做出最终选择后得到通知
这是一个简化的例子。真正的组件更复杂,但原理是一样的:正如日期拾取组件可能有许多内部状态,而拥有该组件的组件却不知道这些状态(例如要显示的时间刻度、要显示的年、月或周等),这个组件也有一些有趣的内部状态,即拥有的组件没有业务管理
据我所知,我做得完全正确。组件通过onChange(event,newValue)
发布其重要状态更新,所有者组件应绑定到该更新。我认为很明显,React决定不更新这些输入上的选中的属性,尽管它显然能够更新相同元素上的其他属性以响应相同的用户操作
请注意,所有者当前没有监听onChange
,但这并不重要:即使所有者没有监听,子组件也应该能够管理自己的内部状态。我拒绝接受无线电状态不准确的断言,因为所有者没有通过道具提供currentValue
:小部件在没有道具的情况下管理和呈现其状态。React必须执行一些特殊操作,以防止根据应用于所有其他元素和属性的规则处理选中的
。这是一个例外,我认为这是一个糟糕的例外
最后,请注意,只有当该组件低于某个comp树深度时,才会出现此问题。当它是
import React from 'react';
import Widget from 'components/widget';
class Owner extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
let choices = [
{ value: 10, label: 'First' },
{ value: 20, label: 'Second' },
{ value: 30, label: 'Third' }
];
return (
<div className="Owner">
<Widget
choices={choices}
/>
</div>
);
}
}
export default Owner;
class Widget extends React.Component {
constructor(props) {
super(props);
this.state = {
currentValue: null // tracks currently-selected choice, by its value
};
this.onClickOptionRadio = this.onClickOptionRadio.bind(this)
this.onConfirm = this.onConfirm.bind(this)
}
onClickOptionRadio (event) {
this.setState({
currentValue: String(event.currentTarget.value)
});
}
onConfirm (event) {
if(!this.props.onChange) return;
this.props.onChange(this.state.currentValue);
};
render() {
let choices = this.props.choices;
let currentValue = this.state.currentValue;
return (
<div className="Widget">
<ol className="choices">
{
choices.map((choice, i) => {
// decide whether to mark radio as checked:
// - if no current choice, check first radios
// - otherwise, check radio matching current choice
let noCurrentChoice = (currentValue === null);
let drawingFirstChoice = (i === 0);
let thisChoiceIsSelected = (String(choice.value) === currentValue);
let checkThisOption = thisChoiceIsSelected || (noCurrentChoice && drawingFirstChoice);
return (
<li key={i}>
<input type="radio" name="choices"
value={choice.value}
onChange={this.onClickOptionRadio}
checked={checkThisOption?'checked':''}
data-ischecked={checkThisOption}
/>
<label>{choice.label}</label>
{' '}
{checkThisOption ? 'CHECKED' : ''}
</li>
);
})
}
</ol>
<button onClick={this.onConfirm}>Confirm choice</button>
</div>
);
}
}
class Owner extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
let choices = [
{ value: 10, label: 'First' },
{ value: 20, label: 'Second' },
{ value: 30, label: 'Third' }
];
return (
<div className="Owner">
<Widget
choices={choices}
/>
</div>
);
}
}
ReactDOM.render(
<Owner />,
document.getElementById('container')
);