Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using debouncer with React event

I have an onchange event for a field that needs to be debounced, I'm using underscore for that, however when I use the debouncer the event that is passed to the React handler appears to be out of date.

<div className='input-field'>
  <input onChange={_.debounce(this.uriChangeHandler.bind(this), 500)} id='source_uri' type='text' name='source_uri' autofocus required />
  <label htmlFor='source_uri'>Website Link</label>
</div>

uriChangeHandler(event) {
    event.preventDefault();
    let uriField = $(event.target);
    let uri = uriField.val();
    this.setState({
        itemCreateError: null,
        loading: true
    });
    this.loadUriMetaData(uri, uriField);
}

I'm getting this error:

Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're calling preventDefault on a released/nullified synthetic event. This is a no-op. See https‍://fb‍.me/react-event-pooling for more information.

Using the onchange without the debouncer works fine.

like image 619
rcjsdev Avatar asked Feb 16 '16 14:02

rcjsdev


People also ask

How do you debounce an event React?

You have 2 options to create debounced and throttled functions in React: using useCallback() or useMemo() hooks.

Should I use throttle or debounce?

Like debounce, throttle is also used to limit the number of times a function is called, but, unlike debounce, throttle will call the function passed to it every time the delay ends as long as the trigger for the function is still happening.

What is event Debounce?

What is debounce? Debounce delays the processing of a function bound to a certain user input event until a certain amount of time has passed. In other words the function is only executed once per specific user input event, even it the event is triggered multiple times.


2 Answers

I ended up with a solution I saw on github which worked well for me. Basically you wrap the debounce function in a custom function debounceEventHandler which will persist the event before returning the debounced function.

function debounceEventHandler(...args) {
  const debounced = _.debounce(...args)
  return function(e) {
    e.persist()
    return debounced(e)
  }
}

<Input onChange={debounceEventHandler(this.handleInputChange, 150)}/>

This got rid of the synthetic event warning

like image 166
xiao Avatar answered Oct 21 '22 07:10

xiao


in yout case it might help

class HelloWorldComponent extends React.Component {
  uriChangeHandler(target) {
    console.log(target)
  }

  render() {
    var myHandler = _.flowRight(
      _.debounce(this.uriChangeHandler.bind(this), 5e2),
      _.property('target')
    );
    return (      
      <input onChange={myHandler}  />
    );
  }
}

React.render(
  <HelloWorldComponent/>,
  document.getElementById('react_example')
);

JSBin

Also you can use _.clone instead of _.property('target') if you want to get the complete event object.

EDITED

To prevent React nullifies the event you must call event.persist() as stated on React doc:

If you want to access the event properties in an asynchronous way, you should call event.persist() on the event, which will remove the synthetic event from the pool and allow references to the event to be retained by user code.

And hence you could use e => e.persist() || e instead of _.clone JSBin

like image 28
ZigGreen Avatar answered Oct 21 '22 08:10

ZigGreen