繁体   English   中英

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

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

我有一个<input type="checkbox"/>元素的引用,当我以编程方式在元素上设置checked=false时,不会调用元素的onChange回调。

我尝试使用ref.dispatchEvent(new Event('input'))ref.dispatchEvent(new Event('change'))并且都没有导致 React onChange回调被执行。

我可以在 StackOverflow 上找到的所有关于此的问题和答案都与<input type="text"/>元素有关,没有涉及以编程方式在<input type="checkbox"/>元素及其onChange上更改checked的属性处理程序未被调用。

这是一个演示该问题的 CodePen:

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

您可以选中和取消选中复选框, <div>Checked!</div>将按预期出现和消失。 但是,单击<button>Reset</button>将取消选中复选框(如果已选中),但由于未执行inputonChange处理程序,因此div并未按应有的方式隐藏。

...

是的,我知道我可以将其作为受控组件来执行,但这不是重点:我有一个需要使用 refs 的用例,因此我必须将其实现为不受控制的 Component ,并在 DOM 元素时执行onChange处理程序变化是我需要解决的问题。

谢谢!

最好以“反应方式”做事。

这意味着,不要使用命令式代码操作 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"));

这是更新笔的链接: https://codepen.io/zuze-lab/pen/QWKVEbY?editors=0011

编辑:我想非常清楚,裁判还不错,一点也不。 许多 React 库都暴露了 refs,因为命令式代码对这些库 API 有意义。 当使用 refs 添加事件侦听器或命令式操作元素时,您做错了事,您需要备份。

这是工作代码。 工作链接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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM