web-dev-qa-db-fra.com

Avertissement: cet événement synthétique est réutilisé pour des raisons de performances se produisant avec <input type = "checkbox" />

J'ai travaillé sur un simple exemple de réaction-redux pour une classe et je suis tombé sur plusieurs messages d'avertissement qui s'affichent dans la console chaque fois que je vérifie et décochez une entrée de case à cocher.

Vous pouvez voir les avertissements dans les images suivantes.

Warning Error Image

J'ai également fait une recherche Google pour le message d'avertissement, mais je n'ai trouvé aucune solution qui fonctionne. En outre, ce qui m'a frappé, c'est qu'il semble qu'il essayait d'accéder à toutes les propriétés de l'événement natif et de l'élément DOM.

Ceci est le code du composant de présentation qui a la case d'entrée

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;

J'ai également téléchargé l'exemple sur CodeSandbox: https://codesandbox.io/s/k0mlxk1yqv

Si vous souhaitez reproduire cette erreur, vous devez ajouter un élément à la liste des tâches et cliquer sur la case à cocher pour cocher et décocher plusieurs fois.

Si quelqu'un a une idée de la raison pour laquelle ces panneaux d'avertissement continuent d'apparaître et comment les désactiver, j'apprécierais beaucoup votre contribution :)

12
Raymi

Je suggère d'essayer deux solutions:

Premier changement

onChange={this.handleCheckbox}

à

onChange={() => this.handleCheckbox}

Si cela ne fonctionne pas, dans 'handleCheckbox' ajoutez cette ligne

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

Cela est dû au fait que le event passé implicitement à onItemClick est utilisé dans un contexte asynchrone.
Comme l'a dit André Lemay, vous devez attribuer vos besoins à des variables locales et les référencer.

Dans mon cas, j'avais ce code:

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

Ensuite, je l'ai changé en:

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

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

Cela peut être un peu tard, mais je viens de rencontrer le même problème et résolu d'une manière qui, je pense, pourrait être meilleure que la réponse d'Adam Orlov. Je ne crois pas que l'une ou l'autre réponse soit directement applicable à la question posée, mais cela se produit lorsque vous recherchez des événements synthétiques et des cases à cocher, c'est donc un endroit aussi bon que n'importe quel autre ...

Je crois qu'Adam a raison de croire que React effacera essentiellement toutes les propriétés de l'objet SyntheticEvent (ce qui est logique, car React nous dit qu'il réutilise L'object).

Cependant, à moins que vous n'ayez besoin de l'intégralité de l'objet, je ne pense pas que l'appel à event.persist () soit la meilleure solution, car selon la documentation , cela supprimera l'objet du pool (vraisemblablement ils mettent là pour une bonne raison).

Si vous souhaitez accéder aux propriétés de l'événement de manière asynchrone, vous devez appeler event.persist () sur l'événement, ce qui supprimera l'événement synthétique du pool et permettra aux références à l'événement d'être conservées par le code utilisateur.

Au lieu de cela, si vous n'avez besoin que d'une ou deux valeurs de l'objet événement, vous pouvez simplement les affecter à des variables locales, puis référencer les variables locales à l'intérieur de votre propre fonction, comme ceci:

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

De cette façon, vous n'avez pas à restructurer votre code de quelque manière que ce soit pour éviter de faire quelque chose d'async qui repose sur des données d'événement, et vous n'avez pas non plus à vous soucier des impacts potentiels sur les performances lorsque vous le permettez React pour faire ce qu'il veut avec le pool d'événements.

4
Andre Lemay