[英]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.