代码之家  ›  专栏  ›  技术社区  ›  RA.

隐藏的输入不会触发React的onChange事件

  •  1
  • RA.  · 技术社区  · 5 年前

    hidden 输入不触发 input 也不是 change 事件。但是,即使我手动触发它们 onChange 事件仍未被调用。

    我两个都触发了, 输入 事实上 事件。当我在 inputRef ( addEventListener("change", () => { ... }) )出于测试目的,调用它没有问题。然而,事实证明React在拦截它时遇到了一些问题。

    这是我目前的代码:

    const [fieldValue, setFieldValue] = useState(0);
    const inputRef = useRef<HTMLInputElement>(null);
    
    const handleClick = useCallback((): void => {
        if (inputRef.current) {
            inputRef.current.dispatchEvent(new Event("change", { bubbles: true }));
            inputRef.current.dispatchEvent(new Event("input", { bubbles: true }));
        }
    
        setFieldValue(prev => prev + 1);
    }, []);
    

    JSX公司:

    <input type="hidden" ref={inputRef} value={fieldValue} onChange={(e) => { console.log("React:onChange"); }} />
    <button type="button" onClick={handleClick}>Hit it</button>
    

    onChange公司

    0 回复  |  直到 5 年前
        1
  •  5
  •   Julien Grégoire    5 年前

    SimpleEventPlugin公司 (见 https://github.com/facebook/react/blob/master/packages/react-dom/src/events/SimpleEventPlugin.js

    合成事件 没有太多变化。

    更改事件由 更改事件插件 https://github.com/facebook/react/blob/master/packages/react-dom/src/events/ChangeEventPlugin.js

    这个插件创建了一个 onChange 规范化更改事件的事件 更改元素的值而不显示闪烁。

    https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event

    对于某些元素,包括更改事件

    但对于React,它的触发方式是不同的,每次值的变化。为此,它由具有以下限制的插件处理:

      color: true,
      date: true,
      datetime: true,
      'datetime-local': true,
      email: true,
      month: true,
      number: true,
      password: true,
      range: true,
      search: true,
      tel: true,
      text: true,
      time: true,
      url: true,
      week: true
    

    所以对于隐藏的输入,react停止调度。

    另一个限制是,只有当输入值发生实际更改时,才会调度事件。看到了吗

     if (updateValueIfChanged(targetNode)) {
        return targetInst;
      }
    

    因此,即使在支持的输入上,您的分派也不会通过插件。您可以在这个代码段中看到它,通过操作一个用于获取输入值的方法,您可以设法调度事件。

    class Hello extends React.Component {
      constructor(props) {
        super(props);
        this.myRef = React.createRef();
    
      }
    
      componentDidMount() {
      //_valueTracker.getValue is used for comparing the values of the input. If you write fake value in the input it'll dispatch, anything else won't
        document.getElementsByTagName('INPUT')[0]._valueTracker.getValue = () => {
          return 'fake value'
        }
      }
    
      render() {
    
        const handleClick = () => {
          if (this.myRef) {
    
            this.myRef.current.dispatchEvent(new Event("change", {
              bubbles: true
            }));
    
    
          }
        };
    
        return <div > < input type = "text"
        ref = {
          this.myRef
        }
        onChange = {
          (e) => {
            console.log("React:onChange");
          }
        }
        /><button type="button"  onClick={handleClick}>Hit it</button > < /div>
    
      }
    }
    
    ReactDOM.render( <
      Hello name = "World" / > ,
      document.getElementById('container')
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    
    <div id="container">
    
    </div>

    因此,对于隐藏的输入,无法使其工作(请注意,它符合标准)。对于文本(或其他受支持的输入),您可以但需要或多或少地修改方法,将事件前的值与事件后的值进行比较。

        2
  •  2
  •   Matthew Barbara    5 年前

    onChange事件被触发 when the user alters 元素值-在您的例子中,您正在以编程方式更改输入值,因此 onChange 没有启动

    onInput events fires 当值改变时-不管怎样。因此您需要添加 输入 .

    <input type="hidden" ref={inputRef} value={fieldValue} onInput={(e) => { console.log("React:onChange"); }} />
    
    

    下面是一个工作示例: Sandbox

        3
  •  0
  •   Andy    5 年前

    我想你可能走错路了。单击按钮时,希望状态更新,并且新状态反映在隐藏字段中。与其检查隐藏字段中的更改,不如检查状态中的更改,您可以很容易地使用它 useEffect . 这样你就不用裁判了,也不用把事情搞得太复杂了。

    function App() {
      const [fieldValue, setFieldValue] = useState(0);
    
      function handleClick() {
        setFieldValue(prev => prev + 1);
      }
    
      useEffect(() => {
         console.log('React:changed');
      }, [fieldValue]);
    
      return (
        <>
          <input type="hidden" value={fieldValue} />
          <button type="button" onClick={handleClick}>
            Hit it
          </button>
        </>
      );
    }
    

    Sandbox