单选按钮中的 onChange 导致状态中的值发生意外更改

Posted

技术标签:

【中文标题】单选按钮中的 onChange 导致状态中的值发生意外更改【英文标题】:onChange in radio button causing undesired change of values in the state 【发布时间】:2021-12-16 21:26:06 【问题描述】:
const [toggleValue, setToggleValue] = useState();
..
..
    Items.map((item) => (
      <Card onClick=() => setToggleValue(item.id) key=item.id>
        <CardHeader text=item.text />
        <Collapse isOpen=toggleValue=== item.id>
          <CardBody>
               <FormGroup>
                  <CustomInput value="1" type="radio" id="yes" onChange=handleOptionChange(item.id, '1') />
                  <CustomInput value="2" type="radio" id="yes" onChange=handleOptionChange(item.id, '2') />
               </FormGroup>
          </CardBody>
        </Collapse>
     </Card>

它按预期工作,但是当我使用单选按钮在这些卡片中选择一个选项时,它会自动折叠当前卡片并展开第一张卡片。在进行单选按钮选择时触发的 handleOptionChange 函数也使用 useState 更改状态中的不同值:

const handleOptionChange = (name, value) => () => 
   const Item = name;
   const numericValue = Number(value);
   setFormData(
      ...data,
      id: Item,
      vote: numericValue,
   );
;

【问题讨论】:

【参考方案1】:

handleOptionChange(item.id, '1') 不应在 onChange 上直接调用

const [toggleValue, setToggleValue] = useState();
..
..
    Items.map((item) => (
      <Card onClick=() => setToggleValue(item.id) key=item.id>
        <CardHeader text=item.text />
        <Collapse isOpen=toggleValue=== item.id>
          <CardBody>
               <FormGroup>
                  <CustomInput value="1" type="radio" id="yes" onChange=()=>handleOptionChange(item.id, '1') />
                  <CustomInput value="2" type="radio" id="yes" onChange=()=>handleOptionChange(item.id, '2') />
               </FormGroup>
          </CardBody>
        </Collapse>
     </Card>

【讨论】:

【参考方案2】:

改变这个

<CustomInput value="1" type="radio" id="yes" onChange=handleOptionChange(item.id, '1') />

进入这个

<CustomInput value="1" type="radio" id="yes" onChange=() => handleOptionChange(item.id, '1') />

原因,正确的原因

对于没有() =&gt;onChange=() =&gt; ....,同样是在组件挂载时运行该函数,无需等待任何用户操作。

您可以通过警报进行测试

onChange=() =&gt; alert('will run only when user change')

...

onChange=alert('Will not wait for user and run when component mount')

【讨论】:

当我这样做时,handleOptionChange 函数不会在单击单选按钮时调用,并且单选值未设置为状态。我注意到单选按钮未正确单击。【参考方案3】:

javascript 事件将冒泡到最近的具有事件监听器的父级

所以在这种情况下,当您单击单选按钮时,它实际上会触发一个 onClick 事件,该事件会冒泡到 Card 组件的 onClick 事件侦听器,从而调用 onClick setToggleValue 函数

您可以将onClick=(event)=&gt;event.stopPropagation() 添加到您的 CustomIInput 组件以防止这种行为

【讨论】:

我得到 event is deprecated 错误,在 VSCode 中划掉了“event”这个词。 抱歉应该是onClick=(event)=&gt;event.stopPropagation() 这应该解决 Card collapsing 问题,其他两个答案应该解决错误 value 问题 谢谢,这解决了卡崩溃的问题。但是,当我使用其他两个答案时,状态值没有得到更新,并且单选按钮没有正确单击。

以上是关于单选按钮中的 onChange 导致状态中的值发生意外更改的主要内容,如果未能解决你的问题,请参考以下文章

onClick和onChange不会在reactjs中的safari单选按钮上触发

更改单选按钮选中状态时如何从单选按钮组中的单选按钮获取文本

如何在UnChecked时触发单选按钮的OnChange事件

将状态设置为单选按钮标签的值

React.js - 如何设置选中/选中的单选按钮并跟踪 onChange?

Input 控件的Onchange 与onBlur 事件区别?