Skip to content
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

Template ref array is updated twice when an array ref dependency is changed #9908

Open
abu-co opened this issue Dec 24, 2023 · 5 comments
Open

Comments

@abu-co
Copy link

abu-co commented Dec 24, 2023

Vue version

3.3.13

Link to minimal reproduction

https://play.vuejs.org/#eNp9Ul1P20AQ/CurE1Ic4Tpt0/YhcoxaFImiFqqSt1wkXGcdDuw76z7cIMv/nT1/hDwg3nwzs vZ2W3Y96qKaodswWKTaVFZMGhdBUUq90vOrOEs4VKUldIWGshUWTmLuxA05tBCrlUJE2ow4ZLLTEljQbryH2oDS68JNp/Cz F8Ox3ZB2EvlZN2oD8SMVJYYInSDpXx1fr3r1UPbbZJsHntkZFidBIEU1gm0HAJx95RnRYOz889pmkcLeH rMl6GC4uYDJpT3521lzf3d5Exmoh9yJ/DkauL5i2nMt7LtvOKsWzFiUqZ4c/D MOzZew RJ Db9tQ/CjxbM VcqQHhbLqkgt0gsgrjQmDUUKbRvP/KNHkytBEw4REX8MrJP1op2oof6QK00rkiDkaIIznxyB4wQELJ7w2ctokdRNdm2onhrFsxNDLKRlU7y52EePRkm6iC5TznzSokB9W1lB8XO26NP2XFoU6v91h1ntMBzx7AGzpzfwR3PwGGd/NBrUNXJ25Gyq92h7enV3gwf6PpKl2rmC1O Qf9GownmPveyHkzuyfaLr3P7sbpk2vTarg0VpxqG8Ua9sOz1ndNWX74z ancezbs6OhHWvgBYwByK

Steps to reproduce

Please observe the output from the computed property c.

What is expected?

elements should only update once when numbers is updated.

What is actually happening?

elements is first set to [] before it is populated, causing any dependent computed properties to be evaluated twice.

System Info

No response

Any additional comments?

Perhaps this behaviour is intentional? 🤔

@edison1105
Copy link
Member

edison1105 commented Dec 25, 2023

fixed by #5912 (in version 3.4)

Switch to version 3.4 DEV mode will get a maximum recursive error.
/cc @johnsoncodehk

I made a pr to fix this, see #9920

@edison1105
Copy link
Member

@abu-co
You should avoid using self-referencing in the computed. it will get an error in version 3.4.
see more #9920 (comment)

@abu-co
Copy link
Author

abu-co commented Dec 26, 2023

You should avoid using self-referencing in the computed. it will get an error in version 3.4.

@edison1105 Noted! Thanks for pointing that out.

fixed by #5912 (in version 3.4)

Hmm... the computed property still appears to have been evaluated twice when a single modification was made to its dependency in the latest version of Vue, though?

Please have a look at this further simplified demo, which uses the version containing the latest commit 0695c69: https://play.vuejs.org/#__DEV__eNp9Ul1v00AQ/CurU6UmqnEKAR6CEwmqSFBBi2jecpFqnHV6rb1n3YdJZfm/s2fHaR6qvnlnZ dmZ92Ir1UV1x7FTCQ2M6pyYNH5CoqUdnMpnJViIUmVlTYOGsh0WXmH2wgM5tBCbnQJ5yxwLklSpsk6IF/ RWNhHjij9fvoQzTdjCUV6OBBuSvtyXHz8mUCCyyR3GEk b769XPZQ vNYrQOwz0xY8ZgYTQaw3wBjSQ4yl5chMrwBobg/kT2rLm u72JrTOKdip/Hg29uE4Lj MWpKQTc2fNULT3klo2IImDWakStXeHpw L9hI8tP4YfYo byK4HH RlEz6QDk LhyWVZE65AogqQwuGk4T2jaZhKJDt6qG l2uDQdPoGh4QIoQC4ODaQZmT/gcaHweFqJOiOdZKJmcvCUiPiFnl6td/Gg18Z27wKQIMaoCzW3lFGcrxayPMvTSotD/rjvMGY/RgGcPmD29gj/afcCk G3QoqlRimPPpWaHrm8v725wz9/HZqm3vmD2G80/aHXhg8ee9s3Tlm2f8Dq3P7o/lI 7ssu9Q7LDUsFoYLYdXwr V6/eWP3F7jSednN8ftH B5gJDxM=

The hitCount is incremented every time c is evaluated.

I'm not really familiar with the internal mechanisms involved here, but I'm guessing this is what is happening:

  1. When elements is initialized to [], c is evaluated for the first time;

  2. When elements is populated with the appropriate references to the elements after render, c is evaluated for the second time;

  3. When numbers is set to a completely different array:

    • elements is first set to [], causing c to be evaluated for the third time (which is unexpected and may cause overhead);
    • elements is then populated with references to the new elements, causing c to be evaluated for the fourth time.

    ... So c is unnecessarily evaluated twice here, despite only one modification being made?

@LinusBorg
Copy link
Member

LinusBorg commented Dec 26, 2023

I think that happens because of this code here:

if (value) {
// #1789: for non-null values, set them after render
// null values means this is unmount and it should not overwrite another
// ref with the same key
;(doSet as SchedulerJob).id = -1
queuePostRenderEffect(doSet, parentSuspense)
} else {
doSet()
}

  • When elements are removed from the template ref array, that happens synchronously
  • Which means the computed is re-evaluated in the current scheduler flush
  • All additions of new elements to the elements array are done as a post render effect,
  • and that triggers the second evaluation of the computed.

From the comments in the source, we can see this was done to solve #1789 so this might be necessary even though it can lead to some double triggers, essentially.

@github-actions github-actions bot locked and limited conversation to collaborators Feb 2, 2024
@yyx990803 yyx990803 reopened this Feb 7, 2024
@vuejs vuejs unlocked this conversation Feb 7, 2024
@yyx990803
Copy link
Member

Change in de4d2e2 led to regressions (#10210, #10234) so it is reverted for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants