React:以编程方式更改组件值不会触发 onChange 事件

Col*_*ini 2 reactjs

我在 React 组件中有一个选择字段,它的值是通过组件状态设置的,并且有一个附加到 onChange 事件的函数。如果我手动更改选择字段值,则会触发 onChange 事件,但如果我通过更改另一个函数的状态值来更改它,则不会触发 onChange 事件。有没有办法以编程方式触发事件?

编辑:

下面是我需要实现的目标的基本示例。这个想法是,当handleChange1()更改state.val2的值(并因此更改在第二个选择字段上选择的选项)时,handleChange2()也会被触发,因此合成事件被传递到父函数(在实际中)代码,选择字段是另一个组件):

class Component extends React.Component {
  state = {
    val1: 1,
    val2: 1,
  }

  handleChange1 = (event) => {
    const val2 = event.target.value === 3 ? 1 : null;
    this.setState({
      val1: event.target.value,
    });
    if (event.target.value === 3) {
      this.setState({
        val2: 1,
      });
    }
    this.props.parentFunction(event);
  }

  handleChange2 = (event) => {
    this.setState({
      val2: event.target.value,
    });
    this.props.parentFunction(event);
  }

  render() {
    return (
        <div>
          <select value={val1} onChange={this.handleChange1}>
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
          </select>
          <select value={val2} onChange={this.handleChange2}>
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
          </select>
        </div>
    );
  }
};
Run Code Online (Sandbox Code Playgroud)

law*_*nce 5

是的,有办法!React 具有阻止onChange以编程方式设置输入值时触发的逻辑,但它可以解决。

代替:

input.value = 'foo';
Run Code Online (Sandbox Code Playgroud)

做这个:

const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
setter.call(input, 'foo');
input.dispatchEvent(new Event('input', { bubbles: true }));
Run Code Online (Sandbox Code Playgroud)

查看这篇文章以获取完整的解释。


如果不清楚, 的值input是您从 ref 获取的 DOM 元素。例子:

function SomeComponent({ onChange }) {
  const ref = useRef();

  useEffect(() => {
    setInterval(() => {
      const input = ref.current;
      const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
      setter.call(input, new Date().toISOString());
      input.dispatchEvent(new Event('input', { bubbles: true }));
    }, 10000);
  });

  return <input type="text" ref="ref" onChange={onChange} />;
}
Run Code Online (Sandbox Code Playgroud)

该组件将使用日期字符串更新其输入,并onChange每 10 秒使用新值触发回调。