-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Add fix for issue 2996 #3046
Add fix for issue 2996 #3046
Conversation
* Add fix for issue 2996. Watch magic had an issue with value reference.
Fix works for user reported Code Pen at: https://codepen.io/dinyo/pen/eYVaKgj?editors=1111 |
I am facing the same issue |
Thanks for creating this pull request @puckowski. I’ve looked at the PR and when calling If this PR gets accepted, the documenation should explain the capabilites/limitation for |
Most recent browsers support structuredClone but it's quite new and you would need a polyfill for the rest (https://github.com/zloirock/core-js#structuredclone). I suppose $watch could warn the user that they should include a polyfill when watching an object then use structuredClone if it exists or your solution otherwise. |
@@ -17,10 +17,10 @@ magic('watch', (el, { evaluateLater, effect }) => (key, callback) => { | |||
queueMicrotask(() => { | |||
callback(value, oldValue) | |||
|
|||
oldValue = value | |||
oldValue = JSON.parse(JSON.stringify(value)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JSON.stringify is expensive, the code already does it at line 12 so you can just assign it to a temp variable and reuse that in here?
}) | ||
} else { | ||
oldValue = value | ||
oldValue = JSON.parse(JSON.stringify(value)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above
* Use strucutredClone for improved watch to avoid object by reference issues.
I reworked my fix to use structuredClone, but it seems Cypress doesn't have access to structuredClone some some checks have failed with the latest push. Users would need to polyfill structuredClone for older browser support from core-js (https://www.npmjs.com/package/core-js) in order for this solution to work. |
* Add warning and try to update Cypress.
* Update focus-trap to version 6.9.4.
* Try to fix focus trap when no autofocus defined.
* Working on focus trap.
* Fixes for focus-trap.
Will scrutinize the changes I have made later today. Had to update Cypress to get access to structuredClone, and also updated focus-trap with a minor code change in the focus index.js. |
* Add Cypress test for watch nested arrays. * Add test for structuredClone support and warn. * Add comments for focus handling of initial focus.
* Refactor to use method to reduce duplicate lines of code.
To summarize, I used structuredClone instead of JSON.parse(JSON.stringify()) which means that users of watch will need to polyfill structuredClone for older browser support. I log a warning if structuredClone is not defined on the window object. I had to update Cypress from 5.5.0 to 9.7.0 in order for the tests to pass (newer version of browser with structuredClone support). Updating Cypress seems to have broken some tests for focus, so I updated focus-trap to 6.9.4 from 6.6.1 and made a small code change with comments to focus index.js. Cypress tests passing and passing in this CodePen. Accidentially closed this pull request for a moment. Still would like to see it merged. FIx also still works for https://codepen.io/dinyo/pen/eYVaKgj?editors=1111 |
* Improve watch edge cases when trying strucutredClone on some proxied objects. * Add watch test for array with objects.
|
// JSON.stringify touches every single property at any level enabling deep watching | ||
JSON.stringify(value) | ||
const shallowClone = (obj) => { | ||
if (typeof obj !== 'object') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi all — just implemented this PR in my own project and got a JS error for my troubles. It was due to this line assuming that if obj
is an object, then it can be parsed by Object.keys — This is incorrect, as null
is also an object, but cannot be parsed:
Object.keys(null)
> Uncaught TypeError: can't convert null to object
I would recommend you add another check for null
, e.g:
if (
typeof obj !== 'object' ||
obj === null
) {
(There may be other clauses needed here but this one got it working for me).
Also: Is it odd that it tested? Apologies, but I didn't have time to look at your test suites.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Not doing this as an official review as I don't know your contrib process. Sorry if I'm stepping on toes here!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies guys but I've also noticed that the watcher only seems to detect the change in value once. No subsequent changes are detected. I've not got a lot of time to look into this properly but thought you should know regardless. Thanks!
* Add support for edge case with null object. * Add two tests for watch for Cypress that deal with null object.
* Update Cypress magic tests to ensure watched value is updated.
* Update Cypress magic tests. Verify old value is being updated correctly.
* Update Cypress magic tests.
* Fix callback not being triggered.
* Update focus for tests.
* Revert focus on element change.
@njpanderson Let me know if this resolves your issue. Old:
|
I've given the latest push a few run throughs @puckowski and not seeing any further issues. Nice work! |
Apologies if this is not the right place to ask, but is there a timeline for this being merged and released? |
No. Caleb has been very busy with the Livewire rewrite and has a been a bit of an absent father to little Alpine. It may not be until after the new Livewire is released. |
Thanks for the PR and all the support! It's well thought out and makes sense. There are a couple of concerns with this PR. One is the size of the implementation, it adds quite a few lines of code, which increases the package size. And the other is using an API that is less than a year old, which may cause issues for end users. We're going to leave it open for the moment, so it can be reviewed in detail. |
As a further follow up, we're going to leave this PR open for now, as Caleb wants to review it in detail, but currently doesn't have time whilst working on Livewire V3. |
Should address: #2996
Cypress tests replicated here and all passing using the patch:
https://codepen.io/puckowski/pen/poLRwEr?editors=1111
39 assertions passing.
User reported in #2996 that the fix solved their issue.