web-dev-qa-db-ja.com

警告:この合成イベントは、<input type = "checkbox" />で発生するパフォーマンス上の理由で再利用されます

私はクラスの単純なreact-reduxのtodoの例に取り組んできましたが、チェックボックスの入力をオンまたはオフにするたびにコンソールに表示されるいくつかの警告メッセージに遭遇しました。

次の画像で警告を確認できます。

Warning Error Image

警告メッセージのグーグル検索も行いましたが、動作する解決策が見つかりませんでした。また、私の注意を引いたのは、ネイティブイベントのすべてのプロパティと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

このエラーを再現するには、ToDoリストにアイテムを追加し、チェックボックスをクリックしてチェックとチェック解除を数回繰り返す必要があります。

この警告サインが表示され続ける理由とそれらを無効にする方法を誰かが知っているなら、あなたの入力を非常に感謝します:)

12
Raymi

2つのソリューションを試すことをお勧めします。

最初の変更

onChange={this.handleCheckbox}

onChange={() => this.handleCheckbox}

うまくいかない場合は、「handleCheckbox」にこの行を追加します

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

これは、eventに暗黙的に渡されるonItemClickが非同期コンテキストで使用されるために発生しました。
Andre Lemayが言ったように、ニーズをローカル変数に割り当てて参照する必要があります。

私の場合、このコードがありました:

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

これは少し遅いかもしれませんが、私は同じ問題に出会い、Adam Orlovの答えよりも良いと思われる方法で解決しました。どちらの答えも質問に直接当てはまるとは思いませんが、シンセティックイベントとチェックボックスをグーグルで検索すると出てくるので、他の場所と同じくらい良い場所です...

Adamは、ReactがSyntheticEventオブジェクトのすべてのプロパティを本質的にクリアすると信じている(Reactがオブジェクトを再利用していることを教えてくれるので理にかなっている)と思います。

ただし、オブジェクト全体が必要な場合を除き、event.persist()を呼び出すことは、プールからオブジェクトを削除する(おそらくそれらを置く) documentation に従って、最良の解決策とは思わないそれには正当な理由があります)。

非同期でイベントプロパティにアクセスする場合は、イベントでevent.persist()を呼び出す必要があります。これにより、プールから合成イベントが削除され、イベントへの参照がユーザーコードによって保持されます。

これを行う代わりに、イベントオブジェクトから1つまたは2つの値のみが必要な場合は、これらをローカル変数に割り当てるだけで、次のように独自の関数内でローカル変数を参照できます。

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

このように、イベントデータに依存する非同期処理を回避するために、コードを再構築する必要はありません。また、Reactを許可することで潜在的なパフォーマンスへの影響を心配する必要もありません。イベントプールで必要な処理を実行します。

4
Andre Lemay