Реакция - Невозможно программно отправить событие onChange из элемента ввода текста - PullRequest
0 голосов
/ 28 декабря 2018

У меня есть два компонента: ParentComponent и ChildComponent.

. В ChildComponent есть элемент input[type="text"], который, когда он меняет свой текст, это событие распространяется на ParentComponent через событиеchange и слушатель onChange.

Приведенный ниже код упрощает более серьезную проблему, поэтому вы увидите некоторые требования, выделенные там.

Моя проблема , что мне нужно для запуска события change внутри функции: handleClick.Я провел несколько экспериментов без удачи.

Здесь у вас есть песочница с кодом , с которой вы можете поэкспериментировать (пожалуйста, предоставьте ответвление с вашим подходом):

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

Есть идеи, как заставить это работать?

Спасибо!

Ответы [ 4 ]

0 голосов
/ 28 декабря 2018

Я исправил ваш код следующим образом: в функции handleChange parentComponent я изменил параметр на значение из события.В childComponent я добавил приведенный ниже вызов функции для функции handleClick:

 this.props.onChange(name);

Почему я сделал эти изменения, потому что вы вызываете функцию handleChange вашего parentComponent из функции onChange вашего childComponent.Когда вы нажимаете кнопку, она вызывает функцию handleClick.В функции handleClick он вызывает свойство onChange.Функция props.onChange вызывает функцию handleChange родительского компонента.handleClick -> this.props.onChange (name) -> this.handleChange (name) Надеюсь, это поможет.

0 голосов
/ 28 декабря 2018

Вы можете включить функцию onClick в родительский компонент, чтобы изменить состояние и передать его в дочерний компонент.В дочернем компоненте вы можете вызвать метод onClick, переданный через реквизит, и передать имя при нажатии кнопки.

Пример кода приведен в приведенной ниже ссылке.

https://codesandbox.io/s/k0n1j2rrx7

0 голосов
/ 28 декабря 2018

Вам не хватает отслеживания изменения входа,

Поскольку React отслеживает, когда вы устанавливаете свойство value на входе, чтобы отслеживать значение узла.Когда вы отправляете событие изменения, оно проверяет его последнее значение по отношению к текущему значению и, если оно совпадает, не вызывает никаких обработчиков событий (поскольку никаких изменений в отношении реакции не произошло).Таким образом, мы должны установить значение таким образом, чтобы функция установки значения React не вызывалась, и именно здесь вступает в игру setNativeValue.

Здесь вы устанавливаете состояние вместо изменения значения входанепосредственно, он не получит обновленное значение при отправке события.и если вы напишите значение непосредственно как input.value, он не сможет отслеживать изменения ввода.

поэтому вы должны установить значение и отправить событие, таким образом вы можете получить обновленное значение при отправке события.

Вот ссылка ссылка и еще один , есть и другие способы, чтобы вызвать событие изменения.

Вот функция, которую вам нужно установить, чтобы реакция могла отслеживать изменения,

  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 голосов
/ 28 декабря 2018

Если я правильно понял, вы пытаетесь изменить родительский текст, например Hello Peter, когда нажимаете кнопку дочернего компонента.

Проверьте мои коды andbox: codesandbox

Изменения:

В дочернем компоненте передайте реквизит, как this.props.onClick(name);

У родителей, получи это как

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

Надеюсь, это тебе поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...