web-dev-qa-db-ja.com

Reactは、クリック時にネストされたコンポーネントでイベントバブリングを防止します

これが基本的なコンポーネントです。 <ul><li>の両方にonClick関数があります。 <li>ではなく、<ul>のonClickのみを起動するようにします。どうすればこれを達成できますか?

E.preventDefault()、e.stopPropagation()をいじってみましたが、役に立ちませんでした。

class List extends React.Component {
  constructor(props) {
    super(props);
  }

  handleClick() {
    // do something
  }

  render() {

    return (
      <ul 
        onClick={(e) => {
          console.log('parent');
          this.handleClick();
        }}
      >
        <li 
          onClick={(e) => {
            console.log('child');
            // prevent default? prevent propagation?
            this.handleClick();
          }}
        >
        </li>       
      </ul>
    )
  }
}

// => parent
// => child
73
dmwong2268

同じ問題がありました。 stopPropagation did workが見つかりました。次のように、リストアイテムを個別のコンポーネントに分割します。

class List extends React.Component {
  handleClick = e => {
    // do something
  }

  render() {
    return (
      <ul onClick={this.handleClick}>
        <ListItem onClick={this.handleClick}>Item</ListItem> 
      </ul>
    )
  }
}

class ListItem extends React.Component {
  handleClick = e => {
    e.stopPropagation();
    this.props.onClick();
  }

  render() {
    return (
      <li onClick={this.handleClick}>
        {this.props.children}
      </li>       
    )
  }
}
96
Will Stone

Reactは、この例の「クリック」のようにバブルするイベントに対して、ドキュメント上の単一のイベントリスナーでイベント委任を使用します。つまり、伝播を停止することはできません。実際のイベントは、Reactでイベントと対話するまでに既に伝播しています。 Reactは内部的に合成イベントの伝播を処理するため、Reactの合成イベントでstopPropagationが可能です。

stopPropagation: function(e){
    e.stopPropagation();
    e.nativeEvent.stopImmediatePropagation();
}
43

これは100%理想的ではありませんが、子供のpropsを引き継ぐのが非常に苦痛であるか、子供のファッションを作成するか、この目的のためにContext.Provider/Context.Consumerを作成する場合just)あなたの前に実行する独自のハンドラを持っている別のライブラリを使用して、あなたも試すことができます:

   function myHandler(e) { 
        e.persist(); 
        e.nativeEvent.stopImmediatePropagation();
        e.stopPropagation(); 
   }

私が理解したことから、event.persistメソッドは、オブジェクトがすぐにReactのSyntheticEventプールに戻されるのを防ぎます。そのため、Reactに渡されたeventは実際に到達するまで存在しません!これは、Reactが最初にSyntheticEventハンドラーの親をチェックダウンすることによって(特に親にコールバックがあった場合)内部で物事を処理する方法のために、孫で発生します。

persistなどのイベントを作成し続けるためにかなりのメモリを作成するものでonMouseMoveを呼び出していない限り(そしておばあちゃんのCookiesのようなCookie Clickerゲームのようなものを作成していない限り)、完全に問題ないはずです!

また、GitHubをときどき読んで、今後のReactのバージョンに目を光らせておく必要がありますmayコンパイラ/トランスパイラーで折りたたみReactコードを作成します。

1
rob2d

これを行うための新しい方法ははるかに簡単であり、時間を節約できます!イベントを元のクリックハンドラーに渡し、preventDefault();を呼び出します。

clickHandler(e){
    e.preventDefault();
    //Your functionality here
}
0
Austin Rowe

event.stopPropagation()の動作に問題がありました。あなたもそうなら、クリックハンドラー関数の一番上に移動してみてください。それは、イベントがバブリングするのを止めるために私がする必要があったことです。関数の例:

  toggleFilter(e) {
    e.stopPropagation(); // If moved to the end of the function, will not work
    let target = e.target;
    let i = 10; // Sanity breaker

    while(true) {
      if (--i === 0) { return; }
      if (target.classList.contains("filter")) {
        target.classList.toggle("active");
        break;
      }
      target = target.parentNode;
    }
  }
0
Nenotlep

イベントのターゲットを確認することにより、イベントのバブリングを回避できます。
たとえば、クリックイベントのハンドラがあるdiv要素にネストされた入力があり、それを処理したくない場合、入力がクリックされたときに、ハンドラにevent.targetを渡してチェックするだけです。ハンドラは、ターゲットのプロパティに基づいて実行する必要があります。
たとえば、if (target.localName === "input") { return}を確認できます。
それは、ハンドラーの実行を「回避」する方法です