admin管理员组

文章数量:1387339

I have the following rather simple React Class:

import React from "react"

export default class DoubleClick extends React.Component {  

  constructor(props) {
    super(props);
    this.state = {
    };
    this.handleClick = this.handleClick.bind(this);
    this.handleDoubleClick = this.handleDoubleClick.bind(this);
  }
  handleClick() {
    console.log("Click");
  }
  handleDoubleClick() {
    console.log("Double Click");
  }
  render() {
    return (
      <div style={{backgroundColor: 'pink'}}>
          <div onClick={this.handleClick}> 
            <span onDoubleClick={this.handleDoubleClick}> Hello </span> 
            <span onDoubleClick={this.handleDoubleClick}> world. </span>
          </div>
      </div>
    );
  }
} 

When somebody single-clicks on the outer div, I want to call handleClick, when somebody double-clicks on any of the inner spans I want to call handleDoubleClick, but not the handleClick for the outer div as well.

However, whenever I double-click, handleDoubleClick() is called, but handleClick is also called, namely twice.

I would like to call handleClick() only when I click, but do not double-click - is this possible?

I have the following rather simple React Class:

import React from "react"

export default class DoubleClick extends React.Component {  

  constructor(props) {
    super(props);
    this.state = {
    };
    this.handleClick = this.handleClick.bind(this);
    this.handleDoubleClick = this.handleDoubleClick.bind(this);
  }
  handleClick() {
    console.log("Click");
  }
  handleDoubleClick() {
    console.log("Double Click");
  }
  render() {
    return (
      <div style={{backgroundColor: 'pink'}}>
          <div onClick={this.handleClick}> 
            <span onDoubleClick={this.handleDoubleClick}> Hello </span> 
            <span onDoubleClick={this.handleDoubleClick}> world. </span>
          </div>
      </div>
    );
  }
} 

When somebody single-clicks on the outer div, I want to call handleClick, when somebody double-clicks on any of the inner spans I want to call handleDoubleClick, but not the handleClick for the outer div as well.

However, whenever I double-click, handleDoubleClick() is called, but handleClick is also called, namely twice.

I would like to call handleClick() only when I click, but do not double-click - is this possible?

Share Improve this question edited Feb 26, 2021 at 22:37 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked Feb 16, 2018 at 20:14 R. KohlischR. Kohlisch 3,0137 gold badges33 silver badges64 bronze badges 8
  • Possible duplicate of onClick works but onDoubleClick is ignored on React ponent – Dez Commented Feb 16, 2018 at 20:16
  • It's not ignored in my case though. – R. Kohlisch Commented Feb 16, 2018 at 20:17
  • But the accepted answer is what you need to know. Not being able to differentiate single from double click in the same DOM ponent is a DOM limitation: stackoverflow./a/25780754/305953 – Dez Commented Feb 16, 2018 at 20:18
  • So it's just not possible to differentiate the two? – R. Kohlisch Commented Feb 16, 2018 at 20:20
  • It is not possible to do reliably. It is possible to implement heuristics to e close with some important limitations such as sacrificing accessibility. As such it wouldn't be advisable, instead try to rearrange your elements so their events don't clash. – Nic Nilov Commented Feb 16, 2018 at 20:28
 |  Show 3 more ments

2 Answers 2

Reset to default 5

I have a HOC that I use to approximate what you're looking for:

import React, { Component } from 'react';
import PropTypes from 'prop-types';

export default class DoubleClick extends Component {
  constructor(props) {
    super(props);
    this.onClick = this.onClick.bind(this);
    this.onDoubleClick = this.onDoubleClick.bind(this);
    this.timeout = null;
  }

  onClick(e) {
    e.preventDefault();

    if(this.timeout === null) {
      this.timeout = window.setTimeout(() => {
        this.timeout = null;
        this.props.onClick();
      }, 300);
    }
  }

  onDoubleClick(e) {
    e.preventDefault();
    window.clearTimeout(this.timeout);
    this.timeout = null;
    this.props.onDoubleClick();
  }

  render() {
    const { onClick, onDoubleClick, children, ...childProps } = this.props;
    const props = Object.assign(childProps, { onClick: this.onClick, onDoubleClick: this.onDoubleClick });
    return React.cloneElement(children, props);
  }
}

DoubleClick.propTypes = {
  onClick: PropTypes.func.isRequired,
  onDoubleClick: PropTypes.func.isRequired,
  children: PropTypes.element.isRequired,
};

Used like this:

<DoubleClick onClick={clickHandler} onDoubleClick={doubleClickHandler}>
  <button>Click or double click me</button>
</DoubleClick>

When the first click is received, it sets a 300ms timeout. If no second click is received within 300ms, the function in the onClick prop will be invoked. If a second click is received within 300ms, the function in the onDoubleClick prop will be invoked, and the timeout is canceled so the onClick does not fire.

Needless to say, this is an imperfect approximation, but I've found it to be a sufficiently satisfying user experience in practice.

Like others said, it's not possible to do a click event on the parent with a doubleClick on the children without a timeout (I think).

If you can sacrifice the UX part of the 500ms until the click is recognized as a non-doubleclick you can work with timeout.

constructor(props) {
    super(props);
    this.state = {
    };
    this.handleClick = this.handleClick.bind(this);
    this.handleDoubleClick = this.handleDoubleClick.bind(this);

    // hack doubleclick
    this.doubleClickTimeout = 500; // default doubleclick timeout
    this.clickedTimeout = null;
  }
  handleClick(ev) {
    if (!this.clickedTimeout) {
      this.clickedTimeout = setTimeout(() => {
        this.clickedTimeout = null;
        // do your stuff here
        console.log('Clicked');
      }, this.doubleClickTimeout);
    }


  }
  handleDoubleClick() {
    clearTimeout(this.clickedTimeout);
    this.clickedTimeout = null;
    console.log("Double Click");

  }
  render() {
    return (
      <div style={{backgroundColor: 'pink'}}>
          <div onClick={this.handleClick}>
            <span onDoubleClick={this.handleDoubleClick}> Hello </span>
            <span onDoubleClick={this.handleDoubleClick}> world. </span>
          </div>
      </div>
    );
  }

本文标签: javascriptPrevent a doubleclick being interpreted as two singleclicksStack Overflow