I wrote a React component like the following code
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. I used e.persist()
at the first line of onMouseDown
function but it destroys the whole process!
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
. 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.
error is that you are appending ripple into the event.target
, which is the button. But you are calling removeChild
on the buttons parent node.
Uncomment e.persist()
and change e.target?.parentNode?.removeChild(ripple);
to e.target?.removeChild(ripple);
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.