簡體   English   中英

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

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

我寫了一個類似下面代碼的 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;
}

可以這樣使用代碼

 <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>

看起來一切正常,但我在瀏覽器控制台中收到此錯誤:

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().

我認為當我在onmousedown事件中使用setTimeout時會出現問題。 我在 onMouseDown function 的第一行使用了onMouseDown e.persist()但它破壞了整個過程!

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

誰能幫我解決這個問題並刪除警告?

我解決了這個問題

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

代替

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

您對e.persist()的想法是正確的,當您調用 function 時,React 會從池中刪除合成事件,這允許異步使用對它的引用,這就是您通過調用setTimeout本質上所做的事情。 你應該堅持這個事件。 您收到NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node. 錯誤是您將漣漪附加到event.target ,這是按鈕。 但是您在按鈕父節點上調用removeChild

取消注釋e.persist()並更改e.target?.parentNode?.removeChild(ripple); e.target?.removeChild(ripple); .

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM