web-dev-qa-db-ja.com

React:ネストされたコンポーネントを介したイベントバブリング

次のようなネストされたコンポーネントがあるとしましょう:

<root />
  <comp1 />
    <comp2 />
      <target id={this.props.id}>
        <div>click me</div>

ターゲットをクリックしてルートで関数を実行したい:

//on root component
this.action = function(id){}

Reactチュートリアルの例のように、チェーン内のすべてのコンポーネントに手動でプロパティを設定する必要がありますか? Jsfiddle

<root />
  <comp1 clickHandler={this.action}/>
    <comp2 clickHandler={this.clickHandler}/>
      <target id={this.props.id} clickHandler={this.clickHandler} />
        <div onClick={this.props.clickHandler.bind(this, this.props.id)}>click me</div>

または、通常のDOMのようにイベントをバブルアップする方法はありますか?

25
kapsi

速記を使用して、小道具を子コンポーネントに渡すことができます

<Component {...this.props} more="values" />

小道具の転送

あなたの場合:

<root />
  <comp1 clickHandler={this.action}/>
    <comp2 {...this.props} />
      <target {...this.props} id={this.props.id} />
        <div onClick={this.props.clickHandler.bind(this, this.props.id)}>click me</div>
5
Clarkie

Reactは、キャプチャ段階とバブリング段階の両方で、仮想DOM全体の合成イベントをサポートしています(ここで説明されているように、 https://facebook.github.io/react/docs/events.html )。

これは、ルートに近い任意のDOM要素にonClickハンドラーを配置でき、ページ上のすべてのClickイベントに対してトリガーする必要があることを意味します。

<root>
  <div onClick={this.handleAllClickEvents}>
    <comp1>
      <comp2>
        <target>
          <div id={this.props.id}>click me</div>

ただし、allクリックイベントに対して発生するため、クリックハンドラーでそれらの間のあいまいさを解消する必要があります(これにより、かなりugいコードが作成されます)。

function handleAllClickEvents(event) {
  var target = event.relatedTarget;
  var targetId = target.id;
  switch(targetId) {
    case 'myBtn1':
      // handle myBtn1 click event
    case 'myBtn2':
      // handle myBtn2 click event
  }
}

このスタイルのイベント委任は、実際にはReactが内部で行うことです( https://shripadk.github.io/react/docs/interactivity-and-dynamic-uis.html #under-the-hood-autobinding-and-event-delegation )そのため、それが本当にやりたいことかどうかを自問する必要があります。

あるいは、FluxのDispatcherパターンのようなものを見たいかもしれません( https://reactjs.org/blog/2014/07/30/flux-actions-and-the-dispatcher.html ) 。始めるのは少し複雑ですが、全体的にはより良いソリューションです。

33
chrismilleruk

最後にクリックされた要素を区別する場合は、Eventオブジェクトを使用して、DOM要素タイプなどの興味深いものを見つけることができます。

<AnElement>
 <button onClick={e => this.eventHandler(e)}>Click me</button>
 <input type="text" onClick={e => this.eventHandler(e)}>Click me</input>

eventHandler = (e) => {
        console.log(e, e.nativeEvent.toElement.nodeName);
...}

そして、クリックした内容に応じてbuttonまたはinputが表示されます。それが私のプロジェクトを探していたものです。

さらに、配列表現でDOMツリーを見つけることができます array representation

それが役に立てば幸い

1
AlexNikonov