React - 无法通过编程方式从输入文本元素触发onChange事件

3
我有两个组件: ParentComponentChildComponentChildComponent 有一个 input[type="text"] 元素,当它改变文本时,该事件通过事件 changeonChange 监听器传播到 ParentComponent
下面的代码是一个更大问题的简化,这就是为什么你会看到一些需要满足的要求。 我的问题是 我需要在函数 handleClick 内触发 change 事件。我进行了一些实验,但没有成功。
以下是可以进行实验的 代码沙盒(请提供使用您的方法的分支): https://codesandbox.io/s/wqw49j5krw 以下是代码: ParentComponent.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>
    );
  }
}

ChildComponent.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>
    );
  }
}

有没有想法让它运行起来?感谢!

你的沙盒链接有效,你实际上想做什么? - Just code
当您单击“Steve”/“Emily”按钮时,“ParentComponent”上的名称不会更新。 - Viewsonic
请查看以下链接:https://dev59.com/6WAg5IYBdhLWcg3wLYaI - Praveen Rao Chavan.G
@Justcode 父组件在子组件中点击“Steve”/“Emily”按钮时,下方的文本不会更新。我需要将事件传递给父组件。 - Viewsonic
@PraveenRaoChavan.G 我尝试了那种方法,但没有成功,这是我的尝试:https://codesandbox.io/s/1q3mpkmrnl。你能在codesandbox.io上提供一些代码分支吗? - Viewsonic
@Viewsonic,您正在尝试获取event.target,而实际上您可以直接使用该值。您可以仅传递该值到函数中,这样它就可以在任何地方被调用,而无需传递事件,只需要传递该值。在您的情况下,这种方法可行吗? - Surya Purohit
4个回答

8

您丢失了输入更改的跟踪信息,

因为React会跟踪当您设置输入的值属性时来保持对节点值的跟踪。 当您调度更改事件时,它会将其上次值与当前值进行比较,如果它们相同,则不调用任何事件处理程序(据React所知,没有进行任何更改)。 因此,我们必须以不会调用React值设置器函数的方式设置该值,这就是setNativeValue发挥作用的地方。

在此处,您正在设置状态而不是直接更改输入的值,因此在调度事件时它将无法获取更新后的值。 如果您像input.value一样直接写入值,则无法跟踪输入的更改。

因此,您应该设置值并调度事件,这样就可以在调度事件时获得更新后的值。

这是referenceanother的链接,还有其他方法可以触发更改事件。

这是你需要设置属性的函数,以便React可以跟踪更改:

  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);
    }
  };

演示


0

您可以在父组件中包含一个onClick函数来改变状态并将其传递给子组件。在子组件中,您可以通过props调用传递下来的onClick方法,并在单击按钮时传递名称。

您可以在下面提供的链接中找到示例代码。

https://codesandbox.io/s/k0n1j2rrx7


0
我已经修改了你的代码: 在parentComponent的handleChange函数中,我将参数从event改为value。 在childComponent中,我添加了以下函数调用到handleClick函数中:
 this.props.onChange(name);

我为什么要做这些更改呢?因为你在子组件的onChange函数中调用了父组件的handleChange函数。当你点击按钮时,它会调用handleClick函数。在handleClick函数中,它调用属性onChange函数。props.onChange函数调用父组件的handleChange函数。 handleClick -> this.props.onChange(name) -> this.handleChange(name) 希望这能帮到你。

-1

如果我理解正确,您正在尝试在单击子组件按钮时更改父级文本,例如Hello Peter

请查看我的codesandbox:codesandbox

更改:

在子组件中,传递一个类似于this.props.onClick(name);的props。

在父级中获取它,如下所示:

  handleClick = name => {
    this.setState({
      name
    });
  };

希望这个可以帮助到你。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接