简体   繁体   English

在 React 事件中使用 setTimeout,出于性能原因重用此合成事件

[英]Using setTimeout inside React event, this synthetic event is reused for performance reasons

I wrote a React component like the following code我写了一个类似下面代码的 React 组件

const RippleEffect = ({ children, controls }: any) => {
  const ctrl = (controls || ['button']) as string[];
  const effect = 'ripple';
  const newChildren = React.Children.map(children, element => {
    const onMouseDown = (e: any) => {
      // e.persist(); Does not work!

      const x = e.pageX - e.target.offsetLeft;
      const y = e.pageY - e.target.offsetTop;
      const w = e.target.offsetWidth.toString();

      const ripple = document.createElement('span');
      ripple.className = 'ripple';
      ripple.style.left = x + 'px';
      ripple.style.top = y + 'px';
      ripple.style.setProperty('--scale', w);
      e.target.appendChild(ripple);

      // Necessary but problematic!
      setTimeout(() => {
        e.target?.parentNode?.removeChild(ripple);
      }, 500);

    };
    if (ctrl.indexOf(element.type) != -1) {
      return React.cloneElement(element, { effect, onMouseDown })
    }
    else {
      return React.cloneElement(element)
    }
  });
  return newChildren;
}

It is possible to use the code in this way可以这样使用代码

 <RippleEffect>
        <button type="button" className="btn btn-primary">Primary</button>
        <button type="button" className="btn btn-secondary">Secondary</button>
        <button type="button" className="btn btn-success">Success</button>
 </RippleEffect>

Looks everything works but I got this error in the browser console:看起来一切正常,但我在浏览器控制台中收到此错误:

Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property `target` on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist().

I think the problem happens when I am using setTimeout inside onmousedown event.我认为当我在onmousedown事件中使用setTimeout时会出现问题。 I used e.persist() at the first line of onMouseDown function but it destroys the whole process!我在 onMouseDown function 的第一行使用了onMouseDown e.persist()但它破坏了整个过程!

NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.

Can anyone help me to fix this issue and remove the warning?谁能帮我解决这个问题并删除警告?

I solved the problem with我解决了这个问题

setTimeout(() => {
    ripple.remove();
}, 500);

instead of代替

setTimeout(() => {
    e.target?.parentNode?.removeChild(ripple);
}, 500);

The idea you have with e.persist() is right, when you call that function, React removes the synthetic event from the pool, and this allows references to it to be used asynchronously, which is what you are essentialy doing by calling setTimeout .您对e.persist()的想法是正确的,当您调用 function 时,React 会从池中删除合成事件,这允许异步使用对它的引用,这就是您通过调用setTimeout本质上所做的事情。 You should persist the event.你应该坚持这个事件。 The reason you are getting NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.您收到NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node. error is that you are appending ripple into the event.target , which is the button.错误是您将涟漪附加到event.target ,这是按钮。 But you are calling removeChild on the buttons parent node.但是您在按钮父节点上调用removeChild

Uncomment e.persist() and change e.target?.parentNode?.removeChild(ripple);取消注释e.persist()并更改e.target?.parentNode?.removeChild(ripple); to e.target?.removeChild(ripple);e.target?.removeChild(ripple); . .

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM