Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么ReactJS处理radio`checked`attr与其他attr不同?_Javascript_Forms_Reactjs - Fatal编程技术网

Javascript 为什么ReactJS处理radio`checked`attr与其他attr不同?

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; 类小部件

tl;drReact拒绝在输入上执行
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')
    );