vuejs / core

🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
https://vuejs.org/
MIT License
47.67k stars 8.33k forks source link

Storing the props in a `const` before passing them in `h` function causes reactivity problems #10773

Closed toyi closed 6 months ago

toyi commented 6 months ago

Vue version

3.4.24

Link to minimal reproduction

https://play.vuejs.org/#eNqlVd9r2zAQ/lcOvcQF48C2Jy8t1KGjHXQba7e9GIZjX2J1smQkOW0J+d93kuMfy9IsZS9G1n26++7T6W7DLus6WjfIYjYzuea1BYO2qS9SyataaQsbKEPQuIQtLLWqYELoSW+9R2Pnqqp3tmjabTink/epTGWupCGvNrMI585TsEklQPX8PRMNXsaQsg9KLTKdsnBkSF4yzPcM27MhSq1VbS4pTBtCFSj8mbiNH63dT9SF9l4nSn6rCzLGA3wSQ+ChZ3B+0fqCgx4okt9wiC1R2WOSnMgkcWkMZ3PSz7kOfPgy6DQNd/mNEnZQF+UFaLIHnR+EnkJx/t9iudh/iOW5zaZt2VHB0Y/FqhZ0kv4AZgVf+wUtFxfXqBFsiSOikJeZXCFwA1JZV1oCc4sFcOmRLmMlUdrZdNE70jDt1r0dYm7OU+Z1T9kAGIE3m11O/dVvKYe/XB5Y9xncZRVCZtrrDWHRWM/SXxQUCo2cuFuSNtvxPyA2CG4sStQRtH67OEfkubk7Ig0EjodarLlqjHiGkvycvUKv5ES9Eq/XKxW7cWTpdumji4FzCI/cliPx6swYys0qv1fCspG55UpCwTWlTWm5A4oSNVZpLlcOVzktMic4PY4FLpVG0qsIAdeonykkwSj2IwoBjb+H4hW6zE/UZb6ro9m0rfbZdPQGWMisIYJLvooejJLUpf37akNwgfpz7fI0KYu7l5eyTAj1+NHvWd2gf7j+TIn5rwP7D+bJ7aXsi0aDeo27futsNtMrtK356u4TPtG6N1KpNYLQR4xf0SjROI4tLGlkQbRHOM/2xk8TUvzeXD1RfZsuKUfU9wuPTxlNFdezXkp9oPs2etf1GVJxPJWOjTolb1Uj3TsZTzs/xro26t8XtbICl1zirfsLfCfrzwZthx26atsH6czkmopJ/VBaFDRC/9kAqVbaaK5E9gvjJ1Wpk4nSoVyjN+/Y9jeTMplp

Steps to reproduce

Nothing special to do except reading the code / look at the preview :)

What is expected?

I'm not even sure this is a bug, but I didn't manage to find an explanation neither here or in the documentation.

The compA component is the cause of this issue, it is the problem.

The compB component may brings a hint about what's happening. Its output is not OK but it is expected, it's just here to bring more infos.

The compC component outputs what is expected in the end:

HelloWorld
HelloWorld

The modelValue change should be reflected in both the child and parent component.

What is actually happening?

In the compA component, the modelValue change is not reflected and it remains at its initial value in the child component, which was Foobar. The state itself is updated, it becomes HelloWorld, but this is not updated in the template of TestComp.vue, only in the parent template.

In the compB component, the props are still stored in a const before being passed to the h function, but without the onUpdate:modelValue listener. Now, the change IS reflected in the template of TestComp.vue, which is what is expected (obviously not in the parent component due to the lack of onUpdate:modelValue listener, this is issue is not about that).

In the compC component, the props are NOT stored in a const before being passed to the h function. Now, the change IS reflected in both the child and the parent templates. Instead of Foobar Helloworld, we now see Helloworld Helloworld, which is what we want.

System Info

System:
    OS: Linux 5.15 Ubuntu 22.04.2 LTS 22.04.2 LTS (Jammy Jellyfish)
    CPU: (12) x64 12th Gen Intel(R) Core(TM) i7-12700K
    Memory: 7.14 GB / 15.62 GB
    Container: Yes
    Shell: 5.8.1 - /usr/bin/zsh
  Binaries:
    Node: 18.20.2 - /usr/local/bin/node
    npm: 10.5.0 - /usr/local/bin/npm
    pnpm: 9.0.1 - /usr/local/bin/pnpm
  Browsers:
    Brave Browser: 123.1.64.122

Any additional comments?

I was trying to make a template system that can take an object as an argument and return a h function. It didn't work and in the end, it shown that passing the props through an object created before the h function was the culprit.

I guess if it's a normal and expected behavior, it should be documented somewhere.

edison1105 commented 6 months ago

The essence of a reactive system is to record the relationship between reactive data and functions. When a function is executed, it accesses the reactive data, so when the reactive data changes, the corresponding function is executed. propsA has already been calculated before compA is executed, therefore myValueA has not established a relationship with compA. The same is true for propsB for the same reason. should be https://play.vuejs.org/#eNqlVd9r2zAQ/lcOv8QB48DWJy8t1KGjHXQba7e9GIZjX2J1smQkOW0J+d93kn/EpG6W0hcj6z7dfffpdLf1Lqsq3NToRd5cZ4pVBjSaurpIBCsrqQxsoQhA4Qp2sFKyhAmhJ731HrVZyLJqbeGs27BOJ58SkYhMCk1eTWoQzq0nf5sIgPL5V8prvIwg8T5LuUxV4gUDQ/yaYXFg2E33USolK31JYfzp+QW0gWSO3J2MGhbhxv6EHQHneyLFzyonY7SHTyLwHXQK5Mz5glEPFM9tWMRuhFDcEjqJT3yQUkZiNhlZFoXfCRy0yfrTA3ATbRQcvwAvRsGn8Fy8Wzcb+6Vu81lTh1SB9GOwrDidpD+Aec42bkHL5cU1KgRT4IAoZEUq1ghMg5DG1hrHzGAOTDikzVgKFGY+W/aOFMy6dW+HiOnzxHPaJ94eMABvt21OfRXsKIcXLkfWfQZ3aYmQ6uaKA1jWxrF0VwW5RC0m9paESVv+I2IDZ9qgQBVC47eLc0Sem7sj0oBvecjlhsla82coyM/0DXrFJ+oVO73eqNiNJUu3Sx+V7zkH8MhMMRCvSrWm3Ix0ewWsapEZJgXkTFHalJY9IClRbaRiYm1xpdUitYLT41jiSiokvfIAcIPqmUISjGI/IudQu3vI36DL4kRdFm0dzWdNtc9ngzfgBZ7RRHDF1uGDloLatntfTQjGUX2rbJ468aLu5SVeyrl8/OL2jKrRPVx3psDs78j+g36ye4n3XaFGtcG2AVubSdUaTWO+uvuKT7TujVRqNSf0EeMP1JLXlmMDi2uRE+0BzrG9ceOFFL/XV09U37pLyhJ1/cLhE4/GjO1Zr6W+p/sxPOv6DKk4HFPHZp8Ut7IW9p0Mx5+ba10bde+LWlmOKybw1v75rpP1Z/2mw+67atMH6czkmopJ/paK5zRT/9sAqVaaaLZEDgvjD1WplYnSoVzDD2fe7h+9EJxl

toyi commented 6 months ago

Thank you for your explanation, it makes sense. I think we can close this issue since there is not much that can be done to improve the DX here.