Search code examples
javascriptreactjslodash

how to pass parameters inside of 'lodash' function(debounce) callback function?


I've been making a component (react.js) that has two events : onClick event and onDoubleClick event.

According to the W3C's DOM spec, it's impossible to distinguish single-click events from click events that lead to a dblclick event.

So I've been making a single event that has a conditional statement.

Here is my inner class component's function code.

    handleClick = (e) => {
     if(!this._delayedClick) {
      this._delayedClick = _.debounce(this.onChangeTargetLabel, 200)
     }
     if(this.clickedOnce) {
      this._delayedClick.cancel()
      this.clickedOnce = false
      this.editLabel()
      console.log('doubleClick')
     } else {
      this._delayedClick(e)
      this.clickedOnce = true
      console.log('Click')
     }
    }

   onChangeTargetLabel = (e) => { // click label event
    console.log(e)
    this.clickedOnce = undefined
    const { label } = this.props
    label.onChangeTargetLabel(e.target.value)
   }

    editLabel = () => { // doubleClick label event
     const { label } = this.props
     label.editLabel()
   }

This code's problems is that once handleClick functions is executed, after 200ms , the debounce callback function is executed , and callback function(this.onChangeTargetLabel) doesn't have any parameters.

I want to bind handleClicks parameter and this.onChangeTargetlabel's parameters.

How can i do that? Thanks.


Solution

  • It's not a good idea to use the event asynchronously, so you could take out the value in the handleClick function and give that to onChangeTargetLabel instead.

    handleClick = e => {
      if (!this._delayedClick) {
        const { value } = event.target;
        this._delayedClick = _.debounce(this.onChangeTargetLabel.bind(this, value), 200);
      }
    
      // ...
    };
    
    onChangeTargetLabel = value => {
      this.clickedOnce = undefined;
      label.onChangeTargetLabel(value);
    };
    

    You could also use a setTimeout instead of a debounced function if you prefer:

    class App extends React.Component {
      timeout = null;
    
      onClick = event => {
        if (this.timeout) {
          console.log("Double click!");
          clearTimeout(this.timeout);
          this.timeout = null;
        } else {
          console.log("click");
          this.timeout = setTimeout(() => {
            this.timeout = null;
          }, 200);
        }
      };
    
      render() {
        return <button onClick={this.onClick}>Click me</button>;
      }
    }