program tip

React는 클릭시 중첩 된 구성 요소에서 이벤트 버블 링을 방지합니다.

radiobox 2020. 10. 5. 07:50
반응형

React는 클릭시 중첩 된 구성 요소에서 이벤트 버블 링을 방지합니다.


다음은 기본 구성 요소입니다. <ul>둘 다 <li>onClick 기능이 있습니다. 나는 onClick 만 <li>발사하고 <ul>. 이것을 어떻게 할 수 있습니까?

나는 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

나는 같은 문제가 있었다. stopPropagation 작동 한다는 것을 알았 습니다. 다음과 같이 목록 항목을 별도의 구성 요소로 분할합니다.

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();  //  <------ Here is the magic
    this.props.onClick();
  }

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

React uses event delegation with a single event listener on document for events that bubble, like 'click' in this example, which means stopping propagation is not possible; the real event has already propagated by the time you interact with it in React. stopPropagation on React's synthetic event is possible because React handles propagation of synthetic events internally.

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

This is not 100% ideal, but if it is either too much of a pain to pass down props in children -> children fashion or create a Context.Provider/Context.Consumer just for this purpose), and you are dealing with another library which has it's own handler it runs before yours, you can also try:

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

From what I understand, the event.persist method prevents an object from immediately being thrown back into React's SyntheticEvent pool. So because of that, the event passed in React actually doesn't exist by the time you reach for it! This happens in grandchildren because of the way React handle's things internally by first checking parent on down for SyntheticEvent handlers (especially if the parent had a callback).

As long as you are not calling persist on something which would create significant memory to keep creating events such as onMouseMove (and you are not creating some kind of Cookie Clicker game like Grandma's Cookies), it should be perfectly fine!

Also note: from reading around their GitHub occasionally, we should keep our eyes out for future versions of React as they may eventually resolve some of the pain with this as they seem to be going towards making folding React code in a compiler/transpiler.


I had issues getting event.stopPropagation() working. If you do too, try moving it to the top of your click handler function, that was what I needed to do to stop the event from bubbling. Example function:

  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;
    }
  }

You can avoid event bubbling by checking target of event.
For example if you have input nested to the div element where you have handler for click event, and you don't want to handle it, when input is clicked, you can just pass event.target into your handler and check is handler should be executed based on properties of target.
For example you can check if (target.localName === "input") { return}.
So, it's a way to "avoid" handler execution


The new way to do this is a lot more simple and will save you some time! Just pass the event into the original click handler and call preventDefault();.

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

참고URL : https://stackoverflow.com/questions/38619981/react-prevent-event-bubbling-in-nested-components-on-click

반응형