簡體   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