[英]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>
将取消选中复选框(如果已选中),但由于未执行input
的onChange
处理程序,因此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.