2017-02-07 4 views
9

イベントから取得する状態フィールドを設定する必要がありますが、関数に渡すと設定されません。コンポーネントおよび方法は、以下のようになります。ReactJSはevent.persist()でイベントから状態を設定できません

constructor(props: SomeProps, context: any) { 
    super(props, context); 
    this.state = { 
    isFiltering: props.isFiltering, 
    anchor: "", 
    }; 
} 

private toggleFilter = (event: any) => { 
    event.persist() 
    this.setState(prevState => ({ 
    isFiltering: !prevState.isFiltering, 
    anchor: event.currentTarget // does not work, it's null 
    })); 
} 

私はevent.persist()を削除した場合、私は次のエラーを取得する:

この合成イベントは、パフォーマンス上の理由のために再利用されます。これが表示されている場合は、リリース/無効化された合成イベントのメソッドcurrentTargetにアクセスしています。これはノーオペレーション機能です。オリジナルの合成イベントを保持しなければならない場合は、event.persist()を使用してください。詳細については、https://facebook.github.io/react/docs/events.html#event-poolingを参照してください。

private toggleFilter = (event: any) => { 
    this.setState({anchor:event.currentTarget}) // works fine 
    this.setState(prevState => ({ 
    isFiltering: !prevState.isFiltering, 
    })); 
} 

はなぜthis.setState(prevState=> ...)を使用しないで上記の作品をんが

:以下のコードが動作するいくつかの理由

+0

私はsetState'が「非同期」である 'ので、あなたがsetState''に渡す機能が実行される(とイベントがアクセスされた)時点でので、それは、だと思う、イベントはnoですもっと長く。 2番目のバージョンでは、イベントは即座にアクセスされ、 'currentTarget'は' setState'に渡されます。 – thirtydot

+0

@thirtydotそれは意味がありますが、それは 'event.persist()'がこれに適した解決策だと思われますが、私にとってはうまく機能しません。 –

+0

うん。私はなぜそれが機能しないのか分からない(自分でそれをテストせずに)、私は答えを書かなかった。 – thirtydot

答えて

6

event.persist()は、実際にはそれがあるべき、currentTargetが無効にされていないことを意味するものではないので、予想される動作だ - それは、ブラウザのネイティブ実装に準拠していますが。

これは、非同期の方法でcurrentTargetにアクセスする場合は、回答で行ったように変数にキャッシュする必要があることを意味します。


Reactコア開発者の1人 - Ben Alpertを挙げると、

イベントがバブルアップするとcurrentTargetが変化します。イベントを受け取った要素とその祖先の他の要素にイベントハンドラがある場合、currentTargetの値は異なって見えます。 IIRCがそれを無効にすることは、ネイティブイベントで起こることと一貫しています。そうでない場合は、私に知らせてください、ここで我々の行動を再考するでしょう。

公式のReactリポジトリの議論のthe sourceと、私が少し触れたBenが提供する次のスニペットを確認してください。

var savedEvent; 
 
var savedTarget; 
 

 
divb.addEventListener('click', function(e) { 
 
    savedEvent = e; 
 
    savedTarget = e.currentTarget; 
 
    setTimeout(function() { 
 
    console.log('b: currentTarget is now ' + e.currentTarget); 
 
    }, 0); 
 
}, false); 
 

 
diva.addEventListener('click', function(e) { 
 
    console.log('same event object? ' + (e === savedEvent)); 
 
    console.log('same target? ' + (savedTarget === e.currentTarget)); 
 
    setTimeout(function() { 
 
    console.log('a: currentTarget is now ' + e.currentTarget); 
 
    }, 0); 
 
}, false);
div { 
 
    padding: 50px; 
 
    background: rgba(0,0,0,0.5); 
 
    color: white; 
 
}
<!DOCTYPE html> 
 
<html> 
 
<head> 
 
    <meta charset="utf-8"> 
 
    <title>JS Bin</title> 
 
</head> 
 
<body> 
 

 
    <div id="diva"><div id="divb"> Click me and see output! </div></div> 
 
    
 
</body> 
 
</html>

1

@thirtydotからのコメントで、私は実用的な解決策を得ました。

setStateは「非同期」なので、setStateに渡す関数が実行される(イベントにアクセスする)までに、イベントはもはや周囲にはありません。第二のバージョンでは、イベントがすぐにアクセスされ、そのは、currentTargetは

をSETSTATEに渡されたので、私は変数にevent.currentTargetを保存し、それがReactJs Event Pooling

に説明しますと、このように見え、それが

を動作することを使用しました
private toggleFilter = (event: any) => { 
     let target = event.currentTarget; 
     this.setState((prevState) => ({ 
      isFiltering: !prevState.isFiltering, 
      anchor: target 
     })); 
    } 

しかし、これはなぜevent.persist()が機能していないかを説明しません。私はそれを説明する答えを受け入れるでしょう。

関連する問題