В ReactJS, как я могу перехватывать (только) двойные щелчки?

Допустим, у меня есть отзывчивый компонент ReactJS (Outer), который что-то делает, когда я нажимаю на него. Внутри более крупного компонента мне нужна единственная кнопка, которая делает что-то особенное, когда я дважды щелкаю ее.

export default function FancyDoubleClickHandler() {
  
  function handleOuterClick() {
    console.log("outer single click")
  }
  
  function handleInnerClick() { 
    ??? 
  }

  return (
    <div id="outer" onClick={handleOuterClick}>
       <p>Click on me to do outer click</p>
       <button id="inner" onDoubleClick={handleInnerClick}>
         <p>
           Click on me to do outer click -- OR --
           Double-click on me to do special inner click thing only
         </p>
       </button>
    </div>
  )
}

Как написано, событие onDoubleClick не препятствует запуску внешнего события onClick (дважды). Эта основная проблема решена в этом вопросе SO, избегая onDoubleClick и вместо этого используется унифицированный обработчик кликов, который запускает одиночные клики только после истечения времени ожидания:

function handleAllClicks(event) {
  clearTimeout(timer);
  
  if (event.detail === 1) {
    timer = setTimeout(() => {
      console.log("SINGLE CLICK");
    }, SOME_DOUBLECLICK_DELAY)

  } else if (event.detail === 2) {
    console.log("DOUBLE CLICK");
  }
}

Но в этом ответе нет необходимости останавливать распространение событий, поэтому двойной щелчок по внутренней кнопке по-прежнему распространяет два события щелчка на handleOuterClick. В моем случае мне нужно подавить эти внешние события в случае двойного щелчка.

В (современном) ReactJS, как я могу создать архитектуру, в которой внутренний элемент перехватывает и обрабатывает двойной щелчок, но распространяет один щелчок вверх?


person Sasgorilla    schedule 17.07.2021    source источник


Ответы (1)


вы не можете остановить вызов события onClick родительского элемента в событии onDoubleClick внутреннего элемента. чтобы остановить распространение событий, вы должны вызвать event.stopPropagation() во внутреннем элементе обработчика события onClick и имитировать в нем двойной щелчок. я надеюсь, что это работает для вас:

function FancyDoubleClickHandler() {
  let timer
  function handleOuterClick() {
    console.log("outer single click")
  }
  function handleInnerClick(e) { 
    e.stopPropagation(); 
    clearTimeout(timer)
    if (e.detail === 1) {
        timer = setTimeout(() => {
         handleOuterClick()
        }, 250);
    }
    if(e.detail === 2) {
      console.log("inner double click");
    }
  }

  return (
    <div id="outer" onClick={handleOuterClick}>
       <p>Click on me to do outer click</p>
       <button id="inner" onClick={handleInnerClick}>
         <p>
           Click on me to do outer click -- OR --
           Double-click on me to do special inner click thing only
         </p>
       </button>
    </div>
  )
}

person arash esmaealbeigi    schedule 17.07.2021
comment
Это многообещающе, однако это решение означает, что я должен знать о любых обработчиках кликов выше в стеке (возможно, в других компонентах). (В моем реальном случае использования внешний элемент представляет собой компонент аккордеона Material-UI, который имеет собственный встроенный обработчик кликов, т. Е. У меня фактически нет доступа к outerClickHandler.) Поэтому я все еще ищу решение, которое распространяет исходное событие. - person Sasgorilla; 18.07.2021