React - 无法以编程方式从输入文本元素调度 onChange 事件

Vie*_*nic 3 html javascript reactjs

我有两个组件:ParentComponentChildComponent

ChildComponent一个元素,当它更改其文本时,该事件将通过事件和侦听器input[type="text"]传播到。ParentComponentchangeonChange

下面的代码是一个更大问题的简化,这就是为什么您会看到其中突出显示的一些要求。

我的问题是我需要触发change函数内的事件:handleClick。我做了一些实验,但没有运气。

这里有您可以试验的代码沙箱(请提供您的方法的分支):

https://codesandbox.io/s/wqw49j5krw

这里有代码:

父组件.js

import React from "react";
import ChildComponent from "./ChildComponent";

export default class ParentComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: "Peter"
    };
  }
  handleChange = event => {
    let target = event.target;
    let value = target.value;
    this.setState({
      name: value
    });
  };
  render() {
    return (
      <div>
        <ChildComponent value={this.state.name} onChange={this.handleChange} /><br />
        <span>Hello</span>&nbsp;
        <span>{this.state.name}!</span>
      </div>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

子组件.js

import React from "react";
import ReactDOM from "react-dom";

export default class ChildComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: this.props.value
    };
  }
  handleChange = event => {
    const name = event.target.value;
    this.setState({ value: name });
    if (this.props.onChange !== undefined) {
      this.props.onChange(event);
    }
  };
  handleClick = name => {
    const inputName = this.refs.name;
    console.log('Name before being changed: ' + inputName.value); // this works
    // PROBABLY HERE IS WHERE THE CODE NEEDS TO BE MODIFIED
    this.setState({ value: name });
    var event = new Event('input', { bubbles: true });
    inputName.dispatchEvent(event); // this doesn't propagate the event to the parent
  };
  render() {
    return (
      <div>
        {"Your name: "}
        <input type="text"
          value={this.state.value}
          onChange={this.handleChange}
          ref="name"
        />
        {/* requirement: the following 2 lines cannot be modified */}
        <button onClick={e => { this.handleClick("Steve"); }}>Steve</button>
        <button onClick={e => { this.handleClick("Emily"); }}>Emily</button>
      </div>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

关于如何让它发挥作用有什么想法吗?

谢谢!

Jus*_*ode 8

你错过了输入变化的轨迹,

因为 React 会跟踪您何时在输入上设置 value 属性以跟踪节点的值。当您分派更改事件时,它会根据当前值检查最后一个值,如果它们相同,则不会调用任何事件处理程序(因为就反应而言,没有发生任何更改)。因此,我们必须以一种不会调用 React 的值设置函数的方式来设置值,这就是 setNativeValue 发挥作用的地方。

在这里,您设置状态而不是直接更改输入的值,因此,当您分派事件时,它不会获得更新的值。如果直接写入值,则input.value无法跟踪输入的变化。

so, you should set the value and dispatch the event, this way you can have the updated value when event is dispatched.

Here is the link of the reference and another, there are other ways too, to fire the change event.

Here is the function you need to set the property so that react can track the changes,

  handleClick = name => {
    const inputName = this.refs.name;
    console.log("Name before being changed: " + inputName.value); // this works

    var event = new Event("input", { bubbles: true });

    this.setNativeValue(inputName, name);
    inputName.dispatchEvent(event);
  };

  setNativeValue = (element, value) => {
    const valueSetter = Object.getOwnPropertyDescriptor(element, "value").set;
    const prototype = Object.getPrototypeOf(element);
    const prototypeValueSetter = Object.getOwnPropertyDescriptor(
      prototype,
      "value"
    ).set;

    if (valueSetter && valueSetter !== prototypeValueSetter) {
      prototypeValueSetter.call(element, value);
    } else {
      valueSetter.call(element, value);
    }
  };
Run Code Online (Sandbox Code Playgroud)

Demo