Javascript 将去抖器与React事件一起使用

Javascript 将去抖器与React事件一起使用,javascript,reactjs,underscore.js,dom-events,debouncing,Javascript,Reactjs,Underscore.js,Dom Events,Debouncing,对于需要取消公告的字段,我有一个onchange事件,我使用了下划线,但是当我使用取消公告器时,传递给React处理程序的事件似乎已过期 <div className='input-field'> <input onChange={_.debounce(this.uriChangeHandler.bind(this), 500)} id='source_uri' type='text' name='source_uri' autofocus required />

对于需要取消公告的字段,我有一个
onchange
事件,我使用了下划线,但是当我使用取消公告器时,传递给React处理程序的事件似乎已过期

<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);
}

网站链接
uriChangeHandler(事件){
event.preventDefault();
让uriField=$(event.target);
让uri=uriField.val();
这是我的国家({
itemCreateError:null,
加载:正确
});
this.loadUriMetaData(uri,uriField);
}
我得到了这个错误:

警告:出于性能原因,将重用此合成事件。如果您看到了这一点,那么您正在对已发布/取消的合成事件调用preventDefault。这是一个禁止操作。请参阅https‍://食品饮料‍.有关详细信息,请参阅me/react事件池


使用
onchange
而不使用去Bouncer可以很好地工作。

我认为正在发生的是,在实际事件和方法被调用之间的时间内,事件被取消。查看(并使用我们所知道的去抖动函数)将告诉您,直到事件触发后500毫秒才调用您的方法。所以你会有这样的事情发生:

  • 事件火灾
  • 设置500毫秒超时
  • React使
    事件
    对象为空
  • 计时器触发并调用事件处理程序
  • 对已为空的事件调用
    event.stopPropagation()
  • 我认为您有两种可能的解决方案:每次事件触发时调用
    event.stopPropagation()
    (在去盎司之外),或者根本不调用它


    旁注:即使使用本机事件,这仍然是一个问题。当您的处理程序实际被调用时,事件已经传播了。React只是在警告你做了一些奇怪的事情时做得更好。

    在你的情况下,它可能会有所帮助

    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')
    );
    
    类HelloWorldComponent扩展了React.Component{
    uriChangeHandler(目标){
    console.log(目标)
    }
    render(){
    var myHandler=\ u0.flowRight(
    _.debounce(this.uriChangeHandler.bind(this),5e2),
    _.property(“目标”)
    );
    报税表(
    );
    }
    }
    反应(
    ,
    document.getElementById('react\u example')
    );
    

    如果要获取完整的事件对象,还可以使用
    .clone
    而不是
    .property('target')

    已编辑

    要防止React使事件无效,必须调用
    event.persist()
    ,如上所述:

    如果希望以异步方式访问事件属性,则应该对事件调用event.persist(),这将从池中删除合成事件,并允许用户代码保留对事件的引用

    因此,您可以使用
    e=>e.persist()| | e
    而不是
    .clone

    我在github上看到了一个解决方案,它对我来说非常有效。基本上,您可以在自定义函数
    debounceEventHandler
    中包装去Bounce函数,该函数将在返回去Bounce函数之前保留事件

    function debounceEventHandler(...args) {
      const debounced = _.debounce(...args)
      return function(e) {
        e.persist()
        return debounced(e)
      }
    }
    
    <Input onChange={debounceEventHandler(this.handleInputChange, 150)}/>
    
    函数debounceEventHandler(…args){
    const debounced=u.debounced(…args)
    返回函数(e){
    e、 坚持
    返回去抖动(e)
    }
    }
    
    这消除了合成事件警告

    类HelloWorldComponent扩展组件{
    
    class HelloWorldComponent extends Component {
        _handleInputSearchChange = (event) => {
            event.persist();
            _.debounce((event) => {
                console.log(event.target.value);
            }, 1000)(event);
        };
    
        render() {
            return (
                <input onChange={this._handleInputSearchChange}  />
            );
        }
    }
    
    _handleInputSearchChange=(事件)=>{ event.persist(); _.debounce((事件)=>{ 日志(event.target.value); },1000)(事件); }; render(){ 返回( ); } }
    这里的想法是,我们希望onChange处理程序先持久化事件,然后立即解除事件处理程序的缓冲,这可以通过以下代码简单地实现:

    <input
    onChange={_.flowRight(
      _.debounce(this.handleOnChange.bind(this), 300),
      this.persistEvent,
    )}
    </input>
    
    persistEvent = e => {
      e.persist();
      e.preventDefault();
      return e;
    };
    
    handleOnChange = e => {
      console.log('event target', e.target);
      console.log('state', this.state);
      // here you can add you handler code 
    }
    
    {
    e、 坚持();
    e、 预防默认值();
    返回e;
    };
    handleOnChange=e=>{
    console.log('event target',e.target);
    console.log('state',this.state);
    //您可以在这里添加处理程序代码
    }
    
    我结合了作者的回答和:

    constmycomponent=()=>{
    const handleChange=useMoom(()=>{
    const debounced=u.debounce(e=>console.log(e.target.value)),1000;
    返回e=>{
    e、 坚持();
    返回去抖动(e);
    };
    }, []);
    返回;
    };
    
    这有帮助吗?不,我用
    this.debouncedUriChangeHandler=\uuu.debounce(this.uriChangeHandler,500)试过了但是得到了相同的错误,谢谢!你能解释一下怎么做吗?我使用了
    .clone
    位而不是
    .property
    这太聪明了这不是一个合适的解决方案。它在每一个变化的事件上都在召唤着黛布思。@xiaolin的解决方案是正确的方法。效果很好!为了便于使用,我将其添加为全球导出。
    const MyComponent = () => {
      const handleChange = useMemo(() => {
        const debounced = _.debounce(e => console.log(e.target.value), 1000);
        return e => {
          e.persist();
          return debounced(e);
        };
      }, []);
      return <input onChange={handleChange} />;
    };