Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react long press event

Is there a way to add long press event in react-web application?

I have list of addresses. On long press on any address, I want to fire event to delete that address followed by a confirm box.

like image 844
Binit Ghetiya Avatar asked Jan 01 '18 10:01

Binit Ghetiya


People also ask

How do you handle double click in react?

To handle double click events in React:Add an onClick prop to the element. Use the detail property on the event object to get the click count. If the click count is equal to 2, handle the double click event.

What is Pressable in react native?

Pressable is a Core Component wrapper that can detect various stages of press interactions on any of its defined children.

How do I create a context menu in react?

Creating a custom right-click menu in React. To create a right-click menu, we need to use the contextmenu event listener. This event fires when the user attempts to open a context menu. It is typically triggered by clicking the right mouse button, or by pressing the context menu keyboard shortcut.


2 Answers

I've created a codesandbox with a hook to handle long press and click. Basically, on mouse down, touch start events, a timer is created with setTimeout. When the provided time elapses, it triggers long press. On mouse up, mouse leave, touchend, etc, the timer is cleared.

useLongPress.js

import { useCallback, useRef, useState } from "react";  const useLongPress = (     onLongPress,     onClick,     { shouldPreventDefault = true, delay = 300 } = {}     ) => {     const [longPressTriggered, setLongPressTriggered] = useState(false);     const timeout = useRef();     const target = useRef();      const start = useCallback(         event => {             if (shouldPreventDefault && event.target) {                     event.target.addEventListener("touchend", preventDefault, {                     passive: false                 });                 target.current = event.target;             }             timeout.current = setTimeout(() => {                 onLongPress(event);                 setLongPressTriggered(true);             }, delay);         },         [onLongPress, delay, shouldPreventDefault]     );      const clear = useCallback(         (event, shouldTriggerClick = true) => {             timeout.current && clearTimeout(timeout.current);             shouldTriggerClick && !longPressTriggered && onClick();             setLongPressTriggered(false);             if (shouldPreventDefault && target.current) {                 target.current.removeEventListener("touchend", preventDefault);             }         },         [shouldPreventDefault, onClick, longPressTriggered]     );      return {         onMouseDown: e => start(e),         onTouchStart: e => start(e),         onMouseUp: e => clear(e),         onMouseLeave: e => clear(e, false),         onTouchEnd: e => clear(e)     }; };  const isTouchEvent = event => { return "touches" in event; };  const preventDefault = event => { if (!isTouchEvent(event)) return;  if (event.touches.length < 2 && event.preventDefault) {     event.preventDefault(); } };  export default useLongPress; 

To use the hook, App.js

import useLongPress from "./useLongPress";  export default function App() {      const onLongPress = () => {         console.log('longpress is triggered');     };      const onClick = () => {         console.log('click is triggered')     }      const defaultOptions = {         shouldPreventDefault: true,         delay: 500,     };     const longPressEvent = useLongPress(onLongPress, onClick, defaultOptions);      return (         <div className="App">             <button {...longPressEvent}>use  Loooong  Press</button>         </div>     ); } 

Older answer for class components:

You can use MouseDown, MouseUp, TouchStart, TouchEnd events to control timers that can act as a long press event. Check out the code below

class App extends Component {   constructor() {     super()     this.handleButtonPress = this.handleButtonPress.bind(this)     this.handleButtonRelease = this.handleButtonRelease.bind(this)   }   handleButtonPress () {     this.buttonPressTimer = setTimeout(() => alert('long press activated'), 1500);   }      handleButtonRelease () {     clearTimeout(this.buttonPressTimer);   }    render() {     return (       <div            onTouchStart={this.handleButtonPress}            onTouchEnd={this.handleButtonRelease}            onMouseDown={this.handleButtonPress}            onMouseUp={this.handleButtonRelease}            onMouseLeave={this.handleButtonRelease}>         Button       </div>     );   } } 
like image 62
sudo bangbang Avatar answered Sep 27 '22 16:09

sudo bangbang


With hooks in react 16.8 you could rewrite class with functions and hooks.

import { useState, useEffect } from 'react';  export default function useLongPress(callback = () => {}, ms = 300) {   const [startLongPress, setStartLongPress] = useState(false);    useEffect(() => {     let timerId;     if (startLongPress) {       timerId = setTimeout(callback, ms);     } else {       clearTimeout(timerId);     }      return () => {       clearTimeout(timerId);     };   }, [callback, ms, startLongPress]);    return {     onMouseDown: () => setStartLongPress(true),     onMouseUp: () => setStartLongPress(false),     onMouseLeave: () => setStartLongPress(false),     onTouchStart: () => setStartLongPress(true),     onTouchEnd: () => setStartLongPress(false),   }; } 
import useLongPress from './useLongPress';  function MyComponent (props) {   const backspaceLongPress = useLongPress(props.longPressBackspaceCallback, 500);    return (     <Page>       <Button {...backspaceLongPress}>         Click me       </Button>     </Page>   ); };  
like image 36
David Avatar answered Sep 27 '22 17:09

David