简体   繁体   English

反应:以编程方式更改选中的 state 时在复选框输入上触发 onChange?

[英]React: trigger onChange on checkbox input when changing checked state programmatically?

I have a ref to an <input type="checkbox"/> element, and when I programmatically set checked=false on the element, the element's onChange callback does not get called.我有一个<input type="checkbox"/>元素的引用,当我以编程方式在元素上设置checked=false时,不会调用元素的onChange回调。

I tried using ref.dispatchEvent(new Event('input')) and ref.dispatchEvent(new Event('change')) and neither caused the React onChange callback to get executed.我尝试使用ref.dispatchEvent(new Event('input'))ref.dispatchEvent(new Event('change'))并且都没有导致 React onChange回调被执行。

All the questions and answers I could find on StackOverflow about this have to do with <input type="text"/> elements, none dealing with changing the checked property programmatically on an <input type="checkbox"/> element and its onChange handler not being invoked.我可以在 StackOverflow 上找到的所有关于此的问题和答案都与<input type="text"/>元素有关,没有涉及以编程方式在<input type="checkbox"/>元素及其onChange上更改checked的属性处理程序未被调用。

Here's a CodePen that demonstrates the issue:这是一个演示该问题的 CodePen:

https://codepen.io/dossy/pen/QWKVNzZ/left/?editors=0011 https://codepen.io/dossy/pen/QWKVNzZ/left/?editors=0011

You can check and uncheck the checkbox, and the <div>Checked!</div> will appear and disappear as expected.您可以选中和取消选中复选框, <div>Checked!</div>将按预期出现和消失。 However, clicking the <button>Reset</button> will uncheck the checkbox if it's checked, but since the input 's onChange handler isn't being executed, the div isn't being hidden as it should be.但是,单击<button>Reset</button>将取消选中复选框(如果已选中),但由于未执行inputonChange处理程序,因此div并未按应有的方式隐藏。

... ...

Yes, I know that I could do this as a Controlled Component but that's not the point: I have a use case where using refs is required so I must implement this as an Uncontrolled Component , and getting the onChange handler to execute when the DOM element changes is the problem I need to solve.是的,我知道我可以将其作为受控组件来执行,但这不是重点:我有一个需要使用 refs 的用例,因此我必须将其实现为不受控制的 Component ,并在 DOM 元素时执行onChange处理程序变化是我需要解决的问题。

Thanks!谢谢!

It's better to do things the "react way".最好以“反应方式”做事。

That means, instead of manipulating dom elements with imperative code (if you're using refs, you're using imperative code), do it declaratively with state/props:这意味着,不要使用命令式代码操作 dom 元素(如果您使用 refs,则使用命令式代码),而是使用 state/props 以声明方式进行操作:

function App() {
  const [checked,setChecked] = React.useState(false);
  return (
    <div className="h-screen flex bg-white text-gray-900 justify-center items-center">
      <div className="flex items-start w-64">
        <div className="flex items-center gap-4">
          <button
            className="inline-flex items-center px-4 py-2 border border-gray-500 rounded-md"
            onClick={() => setChecked(false)}
          >
            Reset
          </button>
          <div>Checkbox:</div>
          <input
            type="checkbox"
            checked={checked}
            onChange={() => setChecked(!checked)}
            className="h-4 w-4 border-gray-300 rounded"
          />
          <div className={checked ? '' : 'hidden'}>
            Checked!
          </div>
        </div>
      </div>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));

Here's a link to the updated pen: https://codepen.io/zuze-lab/pen/QWKVEbY?editors=0011这是更新笔的链接: https://codepen.io/zuze-lab/pen/QWKVEbY?editors=0011

EDIT: I want to be really clear, ref's aren't bad, not at all.编辑:我想非常清楚,裁判还不错,一点也不。 Lots of react libraries expose refs because imperative code makes sense for those libraries APIs.许多 React 库都暴露了 refs,因为命令式代码对这些库 API 有意义。 When using refs to add event listeners, or imperatively manipulate elements, you're doing things wrong and you need to back up.当使用 refs 添加事件侦听器或命令式操作元素时,您做错了事,您需要备份。

Here is the working code.这是工作代码。 working link https://codesandbox.io/s/blissful-wozniak-cc1sn?file=/src/Test.js:0-1753工作链接https://codesandbox.io/s/blissful-wozniak-cc1sn?file=/src/Test.js:0-1753

import React, { useEffect, useRef } from "react";
export function Test() {
  const ref_input = useRef(null);
  const ref_text = useRef(null);
  useEffect(() => {
    ref_input.current.addEventListener("change", function (event) {
      alert(event.target.checked);
    });
  }, []);
  function triggerEvent(element, eventName) {
    var event = document.createEvent("HTMLEvents");
    event.initEvent(eventName, false, true);
    element.dispatchEvent(event);
  }

  return (
    <div className="h-screen flex bg-white text-gray-900 justify-center items-center">
      <div className="flex items-start w-64">
        <div className="flex items-center gap-4">
          <button
            className="inline-flex items-center px-4 py-2 border border-gray-500 rounded-md"
            onClick={() => {
              ref_input.current.checked = false;
              triggerEvent(ref_input.current, "change");
              //ref_input.dispatchEvent(new Event("input"));
              //ref_input.current.dispatchEvent(new Event("onChange"));
            }}
          >
            Reset
          </button>
          <div>Checkbox:</div>
          <input
            ref={ref_input}
            type="checkbox"
            className="h-4 w-4 border-gray-300 rounded"
            // onChange={(e) => {
            //   console.log("onChange called", e.target.checked);
            //   e.target.checked
            //     ? ref_text.current.classList.remove("hidden")
            //     : ref_text.current.classList.add("hidden");
            // }}
          />
          <div ref={ref_text} className="hidden">
            Checked!
          </div>
        </div>
      </div>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 反应:如果输入值因状态而变化,则触发 onChange? - React: trigger onChange if input value is changing by state? 反应:如果输入值由 state 更改且数据来自获取,则触发 onChange? - React: trigger onChange if input value is changing by state with data coming from fetch? 为什么更改 state 中的值不会触发 REACT 中输入元素的 onChange - Why changing value in state doesn't trigger onChange of input element in REACT Checkbox由Z9ED39E2EA2EA931586B6A985A6942EF573EZ驱动到检查时没有响应Onchange - Checkbox doesn't respond to onChange when checked is driven by state 选中复选框时更改输入的值 - Changing Value of an input when a checkbox is checked 以编程方式更改值时如何在文本输入上触发onChange事件-反应 - how to trigger onChange event on text input when the value is changed programmatically - react 选中/取消选中复选框时管理状态-React - Manage State when checkbox is checked/unchecked - React 为什么当 onChange 处理程序设置 state 时反应输入复选框不检查? - Why does react input checkbox not check when onChange handler is setting state? 使用jQuery以编程方式“勾选”复选框 - Trigger a programmatically 'checked' checkbox with jQuery 在输入onChange卡住期间反应改变父状态 - React changing parent state during input onChange getting stuck
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM