Предупреждение: это синтетическое событие используется повторно по причинам, связанным с <input type=checkbox/">

Я работал над простым примером toto-redux todo для класса и наткнулся на несколько предупреждающих сообщений, которые отображаются в консоли каждый раз, когда я проверяю и снимаю флажок ввода.

Вы можете увидеть предупреждения на следующих изображениях.

Warning Error Image

Я также сделал поиск в Google по предупреждению, но не смог найти решение, которое работает. Кроме того, мое внимание привлекло то, что, похоже, он пытался получить доступ ко всем свойствам нативного события и элемента DOM.

Это код для презентационного компонента, который имеет флажок ввода

class TodoItem extends React.Component {
  state = {
    isChecked: false
  };
  handleCheckbox = () => {
    this.setState({
      isChecked: !this.state.isChecked
    });
  };
  render() {
    const { todos, onItemClick } = this.props;
    const { isChecked } = this.state;
    return (
      <div>
        <ul>
          {todos.map((todo, id) => {
            return (
              <li key={id} onClick={onItemClick}>
                <input
                  onChange={this.handleCheckbox}
                  type="checkbox"
                  checked={isChecked}
                />
                <label>
                  <span />
                  {todo.textInput}
                </label>
              </li>
            );
          })}
        </ul>
      </div>
    );
  }
}

export default TodoItem;

Я также загрузил пример на CodeSandbox: https://codesandbox.io/s/k0mlxk1yqv

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

Если у кого-то есть идея, почему эти предупреждающие знаки продолжают появляться и как их отключить, я был бы очень признателен за ваш вклад :)

Ответ 1

Я бы предложил попробовать два решения:

Первое изменение

onChange={this.handleCheckbox}

в

onChange={() => this.handleCheckbox}

Если это не сработает, в 'handleCheckbox' добавьте эту строку

handleCheckbox = (event) => {
event.persist();
this.setState({
  isChecked: !this.state.isChecked
});};

Ответ 2

Это произошло потому, что event, неявно переданный в onItemClick, используется в асинхронном контексте.
Как сказал Андре Лемай, вы должны назначить свои потребности локальным переменным и ссылаться на них.

В моем случае у меня был этот код:

handleInput = e => { // <-- e = synthetic event
  this.setState(state => ({ // <-- asynchronous call
    data: {
      ...state.data,
      [e.target.name]: e.target.value // <-- this was causing the warnings (e.target is in an asynchronous context)
    }
  }));
};

Затем я изменил его на:

handleInput = e => {
  const { name, value } = e.target; // <-- moved outside asynchronous context

  this.setState(state => ({
    data: {
      ...state.data,
      [name]: value
    }
  }));
};

Ответ 3

Это может быть немного поздно, но я только столкнулся с той же проблемой и решил ее так, что я думаю, что будет лучше, чем ответ Адама Орлова. Я не верю, что какой-либо ответ имеет прямое отношение к заданному вопросу, но он возникает при поиске синтетических событий и флажков, так что это хорошее место, как и любой другой...

Я верю, что Адам прав, полагая, что React по существу очистит все свойства объекта SyntheticEvent (что имеет смысл, поскольку React говорит нам, что он повторно использует объект).

Однако, если вам не нужен весь объект, я не думаю, что вызов event.persist() - это лучшее решение, согласно документации, которое удалит объект из пула (предположительно, они поместили его туда по уважительной причине),

Если вы хотите получить доступ к свойствам события асинхронным способом, вы должны вызвать event.persist() для события, которое удалит синтетическое событие из пула и позволит ссылкам на событие быть сохраненными кодом пользователя.

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

<input type="checkbox" onChange={(event) => {
    let checked = event.currentTarget.checked; //store whatever values we need from from the event here
    this._someOtherFunction(checked)
} />

Таким образом, вам не нужно каким-либо образом реструктурировать свой код, чтобы избежать выполнения каких-либо асинхронных операций, основанных на данных событий, и вам также не нужно беспокоиться о потенциальном влиянии на производительность, поскольку вы позволяете React делать то, что ему нужно пул событий.