ReactJS SyntheticEvent stopPropagation ()은 React 이벤트에서만 작동합니까?


126

ReactJS 구성 요소 내에서 event.stopPropagation ()을 사용하여 클릭 이벤트가 버블 링되는 것을 막고 레거시 코드에서 JQuery와 함께 첨부 된 클릭 이벤트를 트리거하려고하는데 React의 stopPropagation ()이 이벤트로의 전파 만 중지하는 것 같습니다. 또한 React에 첨부되어 있으며 JQuery의 stopPropagation ()은 React로 첨부 된 이벤트에 대한 전파를 중지하지 않습니다.

이러한 이벤트에서 stopPropagation ()이 작동하도록하는 방법이 있습니까? 이러한 동작을 보여주기 위해 간단한 JSFiddle 을 작성했습니다 .

/** @jsx React.DOM */
var Propagation = React.createClass({
    alert: function(){
        alert('React Alert');
    },
    stopPropagation: function(e){
        e.stopPropagation();
    },
    render: function(){
        return (
            <div>
                <div onClick={this.alert}>
                    <a href="#" onClick={this.stopPropagation}>React Stop Propagation on React Event</a>
                </div>
                <div className="alert">
                    <a href="#" onClick={this.stopPropagation}>React Stop Propagation on JQuery Event</a>
                </div>
                <div onClick={this.alert}>
                    <a href="#" className="stop-propagation">JQuery Stop Propagation on React Event</a>
                </div>
                <div className="alert">
                    <a href="#" className="stop-propagation">JQuery Stop Propagation on JQuery Event</a>
                </div>
            </div>
        );
    }
});

React.renderComponent(<Propagation />, document.body);

$(function(){    
    $(document).on('click', '.alert', function(e){
        alert('Jquery Alert');
    });

    $(document).on('click', '.stop-propagation', function(e){
        e.stopPropagation();
    });
});

9
React의 실제 이벤트 리스너도 문서의 루트에 있습니다. 즉, 클릭 이벤트가 이미 루트로 버블 링되었습니다. 를 사용 event.nativeEvent.stopImmediatePropagation하여 다른 이벤트 리스너가 실행되는 것을 방지 할 수 있지만 실행 순서는 보장되지 않습니다.
Ross Allen

3
실제로 stopImmediatePropagation클레임 이벤트 리스너는 바인딩 된 순서대로 호출됩니다. React JS가 jQuery 이전에 초기화되면 (피들에있는 것처럼) 즉시 전파를 중지 할 수 있습니다.
Ross Allen

jQuery 리스너가 호출 되는 것을 막는 React : jsfiddle.net/7LEDT/5 jQuery 리스너가 나중에 바이올린에서 바인딩되기 때문에 jQuery가 React가 호출되는 것을 막을 수는 없습니다.
Ross Allen

한 가지 옵션은에서 자체 jQuery 이벤트 핸들러를 설정하는 componentDidMount것이지만 예상치 못한 방식으로 다른 React 이벤트 핸들러를 방해 할 수 있습니다.
Douglas

두 번째 예는 .stop-propagation반드시 작동하지 않을 것임을 깨달았습니다 . 귀하의 예제는 이벤트 위임을 사용하지만 요소에서 전파를 중지하려고합니다. 리스너는 요소 자체에 바인딩되어야합니다 $('.stop-propagation').on('click', function(e) { e.stopPropagation(); });. 이 바이올린을 방지 당신 같은 모든 전파하려고했던 : jsfiddle.net/7LEDT/6
로스 알렌

답변:


165

React는 document이 예제에서 'click'과 같이 버블 링되는 이벤트 에 대해 단일 이벤트 리스너가있는 이벤트 위임을 사용합니다 . 이는 전파를 중지 할 수 없음을 의미합니다. 실제 이벤트는 React에서 상호 작용할 때 이미 전파되었습니다. stopPropagationReact의 합성 이벤트는 React가 내부적으로 합성 이벤트의 전파를 처리하기 때문에 가능합니다.

아래에서 수정 한 JSFiddle 작업 .

jQuery 이벤트에 대한 반응 중지 전파

Event.stopImmediatePropagation루트의 다른 리스너 (이 경우 jQuery)가 호출되지 않도록 방지하는 데 사용 합니다. IE9 + 및 최신 브라우저에서 지원됩니다.

stopPropagation: function(e){
    e.stopPropagation();
    e.nativeEvent.stopImmediatePropagation();
},
  • 경고 : 리스너는 바인딩 된 순서대로 호출됩니다. 이것이 작동하려면 다른 코드 (여기에서는 jQuery)보다 먼저 React를 초기화해야합니다.

React 이벤트에서 jQuery 중지 전파

jQuery 코드는 이벤트 위임도 사용합니다. 즉 stopPropagation, 핸들러에서 호출 해도 아무것도 중지되지 않습니다. 이벤트가 이미에 전파 document되었으며 React의 리스너가 트리거됩니다.

// Listener bound to `document`, event delegation
$(document).on('click', '.stop-propagation', function(e){
    e.stopPropagation();
});

요소를 넘어 전파되지 않도록하려면 리스너를 요소 자체에 바인딩해야합니다.

// Listener bound to `.stop-propagation`, no delegation
$('.stop-propagation').on('click', function(e){
    e.stopPropagation();
});

편집 (2016/01/14) : 위임은 버블 링 이벤트에만 반드시 사용된다는 점을 명확히했습니다. 이벤트 처리에 대한 자세한 내용은 React의 소스에 ReactBrowserEventEmitter.js 라는 설명 주석이 있습니다.


@ssorellen : 설명 : React는 이벤트 리스너를 document이나 루트 React 컴포넌트 에 바인딩 합니까? 링크 된 페이지는 단지 말한다 나는 그것이 의미하기 위해 취할, "최고 수준" 하지document (이도 관련이있는 경우 그러나 나는 알아낼 수 없습니다).
user128216

2
@FighterJet 이벤트 유형에 따라 다릅니다. 버블 링되는 이벤트의 경우 최상위 위임이 사용됩니다. 버블 링되지 않는 이벤트의 경우 React는 반드시 다양한 DOM 노드에서 수신 대기합니다. 보다 철저한 설명은 ReactBrowserEventEmitter.js에 포함되어 github.com/facebook/react/blob/...을
로스 알렌

일시적인 반대 투표에 대해 사과드립니다. 나는 버그 리포트를 위해 그것을 필요로하고 내가 :) upvote에 그것을 대체 한
Glorfindel

또한 전역 클릭 리스너를 window대신 추가 할 것을 제안하는 Jim의 답변을 확인하십시오 document. stackoverflow.com/a/52879137/438273
jsejcksn

13

워스 (에서 주목 이 문제 는 이벤트를 부착하는 경우 있음) document, e.stopPropagation()도움이 될 수 없습니다. 해결 방법으로 window.addEventListener()대신을 사용할 수 있습니다 document.addEventListener. 그러면 event.stopPropagation()이벤트가 창으로 전파되지 않습니다.


대단히 감사합니다! 이것이 바로 내가 가진 것이며이 솔루션이 작동합니다.
Anh Tran

10

여전히 한 번의 흥미 진진한 순간입니다.

ev.preventDefault()
ev.stopPropagation();
ev.nativeEvent.stopImmediatePropagation();

함수가 태그로 래핑 된 경우이 구성을 사용합니다.


1
event.nativeEvent정답입니다. 나는 composedPath()그것을 통해 사용할 수 있었다 :event.nativeEvent.composedPath()
jimmont

무슨 말이야 wrapped by tag? pls는 예를 제공 할 수 있습니까?
JimmyLv

@JimmyLv 내 말은 <div onClick=(firstHandler)> <div onClick=(secHandler)>active text</div> </div>
Roman

7

내 구성 요소에 다음을 추가하여이 문제를 해결할 수있었습니다.

componentDidMount() {
  ReactDOM.findDOMNode(this).addEventListener('click', (event) => {
    event.stopPropagation();
  }, false);
}

2
React는 버블 링되는 이벤트에 대해 문서에서 단일 이벤트 리스너와 함께 이벤트 위임을 사용하기 때문에 SynteticEvents가 모두 중지됩니다.
Vakhtang

5

어제이 문제가 발생하여 React 친화적 인 솔루션을 만들었습니다.

react-native-listener를 확인하세요 . 지금까지 매우 잘 작동하고 있습니다. 피드백에 감사드립니다.


5
react-native-listener사용 findDomNode되지 않는 것 github.com/yannickcr/eslint-plugin-react/issues/...을
의 Bohdan Lyzanets

답변이 완전한 답변을 보완하지 않는 외부 솔루션을 마케팅하거나 제공하기에 적합한 장소가 아니기 때문에 반대 투표를 받았습니다.
jimmont

2

(가)에서 문서 반응 : 아래의 이벤트 핸들러가되어 트리거 이벤트가 버블 링 단계에서 . 캡처 단계에 대한 이벤트 핸들러를 등록하려면 Capture를 추가하십시오 . (강조 추가됨)

당신이 당신의 반작용 코드에서 클릭 이벤트 리스너가 있고 버블에 원하지 않는 경우에, 나는 당신이하고 싶은 것은 사용하는 것입니다 생각 onClickCapture대신 onClick. 그런 다음 이벤트를 핸들러에 전달하고 event.nativeEvent.stopPropagation()네이티브 이벤트가 바닐라 JS 이벤트 리스너 (또는 반응하지 않는 모든 것)로 버블 링되지 않도록합니다.


0

업데이트 : 이제 <Elem onClick={ proxy => proxy.stopPropagation() } />


1
@RossAllen의 답변을 참조하십시오. 이것은 (jQuery가 사용하는) 조상의 네이티브 DOM 리스너로의 전파를 막지는 않습니다.
Ben Mosher

반응 구성 요소를 사용하는 경우 이것이 올바른 방법입니다. 이벤트 하이재킹은 좋은 생각이 아닙니다.
Eric Hodonsky 2011

뭔가 다른 실패하면 당신이 뭔가 다른 잘못을하고있는 때문입니다
에릭 Hodonsky

1
모든 청취자가 React를 통해 연결되는 경우 이것이 올바른 방법이라는 데 동의하지만 여기에서는 문제가 아닙니다.
Ben Mosher

그게 바로 나야 ... 나는 누군가가 문제에 대한 '해결책'을 가지고 있기 때문에 미래에 슬픔을 유발할 수있는 해결 방법으로 누군가를 길을 잃게하는 대신 올바른 방법을 올바르게 사용하도록 장려 할 것입니다.
Eric Hodonsky

0

빠른 해결 방법은 사용하는 window.addEventListener대신 document.addEventListener.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.