gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:29:29 26 4
gpt4 key购买 nike

tl; dr 即使在同一组输入上完全遵守checked={checkThisOption},React也拒绝遵守输入上的data-ischecked={checkThisOption}

我尚未在jsfiddle上进行此工作,但已使用this code重现了该问题。

长版

我有一个简单的ReactJS组件,向用户显示单选按钮列表。用户应该能够选择收音机,然后按下按钮以确认他们的选择。

这是组件def(注意:我正在使用ES6和webpack):

import React from 'react';

class Widget extends React.Component {
constructor(props) {
super(props);

this.state = {
currentValue: null // tracks currently-selected choice, by its value
};
}

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>
);
}

}

export default Widget;

这是拥有的组件:
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;

这是它的动态效果:

Live demo

请注意视频中的几件事:
  • 该逻辑显然可用于检查初始渲染
  • 上的第一个电台
  • 当用户单击它们时,其他 radio 未选中
  • ,但是该逻辑显然可用于识别选择了哪个项目,如收音机上的margin-right: 2rem所指示的那样,应检查
  • 整个
  • 中指示已选择哪个选项的文本都是准确的
    当我单击一个收音机时,
  • componentWillUpdate方法仅针对Widget本身触发;它的祖先都没有更新

  • 我认为此演示证明这不是 Widget实例被状态为空的其他实例替换的情况。当前选择由输入上的 data- attr以及纯文本准确反射(reflect)的事实表明,状态可以按需要持久化。我确定这种不想要的行为是设计使然,我想知道如何解决React应用于控制输入的与表单相关的属性的奇异,特殊的逻辑。

    为什么我认为当前行为是错误的?我不希望拥有组件知道每次 radio 单击-所有者应绑定(bind)到Widget的 onChange方法,并在做出最终选择后得到通知。

    这是一个简化的示例。真正的组件更加复杂,但是原理是一样的:就像日期收集组件可能具有很多内部状态,而所有者组件却不知道该内部状态(例如显示什么时间范围,要显示的年,月或周)显示等),因此该组件也具有一些有趣的内部状态,即拥有组件无需进行业务管理。

    据我所知,我已经完全正确地做到了。该组件通过 onChange(event, newValue)发布其重要状态更新,拥有组件应绑定(bind)到该更新。我认为很明显,React决定不更新这些输入上的 checked属性,即使它显然能够响应相同的用户操作来更新相同元素上的其他属性。

    请注意,所有者当前未在监听 onChange,但这无关紧要:即使所有者未在监听,子组件也应能够管理其自身的内部状态。我拒绝这样的说法,即 radio 状态不能准确无误,这仅仅是因为所有者没有通过props提供 currentValue:Widget显然是在没有那个prop的情况下管理和呈现其状态。 React必须做一些特殊的事情,以防止 checked根据适用于所有其他元素和属性的规则进行处理。这是一个异常(exception),我认为这是一个坏习惯。

    最后,请注意,仅当此组件在某个压缩树深度以下时,才会出现此问题。如果它是Flux“页面”或Redux“容器”中的唯一组件,则效果很好。如前所述,当它嵌套得更深时,它会失败。我还没有找到一种简洁的方式来显示这一点。

    任何建议表示赞赏。据我所知,这里React违反了自己的既定规则,我希望这种行为会使构建基于vanilla input的其他有状态组件感到沮丧。

    编辑:我为 radio 纠正了生成的 name,并更新了演示以反射(reflect)它。向任何开始追逐这些东西的人表示歉意。

    最佳答案

    我已经将其编辑为不使用class properties,并且无法复制:

    enter image description here

    码:

    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')
    );

    我的浏览器是Chrome47。 Here is the jsfiddle.

    关于javascript - 为什么ReactJS处理radio `checked` attr与其他attrs不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34365705/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com