-
-
Notifications
You must be signed in to change notification settings - Fork 120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Data given to fromData
is mutated by the component
#56
Comments
Marked this as upstream back when it was opened, but never quite responded. Thanks for providing a repro! Upstream Bug, but might have performance implications
I dug a bit deeper upstream in Ideally, this should be copied over instead of using the ref so that mutations don't affect the arguments that were passed in. This is definitely an edge case though, as I've actually never come across a use-case for this. That being said, it's a simple change to fix this, so it could be contributed if there isn't a significant performance penalty to this (i.e. if the data is huge, copying could cause some lag). Next Steps to fix
Part of that change was this PR szimek/signature_pad#570 that changed that line a tiny bit, but did not quite fix this issue for all cases. Given the possible perf implications and the simple workaround available for this edge case, it's possible this won't be accepted though. Workaround Available
Thanks for providing a workaround with your issue! Per my above paragraph, this can be simplified with raw JS so as not to require use of a library like Rambda: canvasRef.current.fromData([].concat(signaturePoints)) Some tests for this workaroundAlso did some tests to make sure that there aren't further pointer issues deeper in the data structure with const signaturePoints = [
[
{ x: 54.002685546875, y: 130.68206787109375, time: 1596180140938 },
{ x: 87.002685546875, y: 86.68206787109375, time: 1596180141056 },
{ x: 114.002685546875, y: 66.68206787109375, time: 1596180141072 },
{ x: 130.002685546875, y: 60.68206787109375, time: 1596180141088 },
{ x: 143.002685546875, y: 60.68206787109375, time: 1596180141104 },
{ x: 150.002685546875, y: 61.68206787109375, time: 1596180141120 },
],
]
const data = [].concat(signaturePoints)
// push is used in signature_pad: https://github.com/szimek/signature_pad/blob/878786ef6ef38bf317d1cf674b3455d39e98d270/src/signature_pad.ts#L299
data.push([
{x: 132.002685546875, y: 110.68206787109375, time: 1596185355643 },
{x: 135.002685546875, y: 106.68206787109375, time: 1596185355725 },
{x: 146.002685546875, y: 98.68206787109375, time: 1596185355741 },
{x: 153.002685546875, y: 94.68206787109375, time: 1596185355757 },
{x: 157.002685546875, y: 91.68206787109375, time: 1596185355790 },
{x: 146.002685546875, y: 98.68206787109375, time: 1596185355741 },
])
console.log(signaturePoints)
// [
// [
// {x: 54.002685546875, y: 130.68206787109375, time: 1596180140938 },
// {x: 87.002685546875, y: 86.68206787109375, time: 1596180141056 },
// {x: 114.002685546875, y: 66.68206787109375, time: 1596180141072 },
// {x: 130.002685546875, y: 60.68206787109375, time: 1596180141088 },
// {x: 143.002685546875, y: 60.68206787109375, time: 1596180141104 },
// {x: 150.002685546875, y: 61.68206787109375, time: 1596180141120 },
// ]
// ] |
Nice investigation, thanks! Cloning the data can indeed have a performance impact. I believe that in this case, it's probably negligible (unless the signature is quite complexe 😄), but it's definitely worth having it in mind. Do you think that a PR changing this: signaturePad.fromData(data, { clear: false }); to this signaturePad.fromData(data, { clear?: boolean, immutable?: boolean }); could have chances of being accepted? (It's not ideal like this, but it's a first step toward having it immutable by default for the next major release 😉) Thanks also for |
Agreed, but figured I'd might as well test this and see to make sure. I did a quick test (see screenshot below) of cloning the full data of a signature and there was no noticeable lag on my end. Of course, this can vary per device (e.g. on a low-end mobile device vs. a beefy laptop), but given that
Now that I've tested the performance I'll try a PR with the clone. If not, I think that's a good alternative, though I would rename the parameter to something like |
Hi @agilgur5 ! That's a really nice and simple PR. I'll keep an eye on it, and as soon as it's merged over there, I'll close this issue. Thank you for your work 🙂 |
Merged! Well done! |
Linked this to #68 and a new tracking milestone as |
To reproduce,
fromData
:signaturePoints
, it'll contain the line you just draw:signaturePoints
has been modified by the component.A workaround to prevent this is to clone the data before passing it to
fromData
:R
being Ramda. EDIT: or use[].concat(signaturePoints)
, or[...signaturePoints]
, which doesn't require a third-party library, to clone the data as agilgur5 recommends below.The text was updated successfully, but these errors were encountered: