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

changes to nonreactive variables containing primitive values are reflected in prod, but not in dev. #5655

Closed
xiexuan-star opened this issue Apr 1, 2022 · 10 comments
Labels
feat: script-setup Related to experimental implementation of RFC #227 🐞 bug Something isn't working 🔩 p2-edge-case
Projects

Comments

@xiexuan-star
Copy link

Version

3.2.31

Reproduction link

sfc.vuejs.org/

Steps to reproduce

const foo = shallowRef({foo:1})

The element node should not be updated when the shallowRef changes.
However, when other responsive data changes, the element node(bound to shallowRef) is also updated

What is expected?

not updated

What is actually happening?

element node updated

@xiexuan-star
Copy link
Author

// Result of compilation
_createElementVNode("div", _hoisted_1, _toDisplayString(_unref(foo).fooProp), 1 /* TEXT */),
    _createElementVNode("div", _hoisted_2, _toDisplayString(bar.value), 1 /* TEXT */),
// I guess both of that should be tagged STATIC or hoisted

@LinusBorg
Copy link
Member

LinusBorg commented Apr 1, 2022

I'm not sure what what you mean with "only happens in SFC playground".

What you see there is normal. when one reactive dependency of the template changes, the whole component is re-rendered, with all the latest data.

So I'm not sure what behavior you expect.

@xiexuan-star
Copy link
Author

I'm not sure what what you mean with "only happens in SFC playground".

https://user-images.githubusercontent.com/30561277/161329929-05c80ef9-c299-422f-82bd-096dbf14874d.mov
Same code in my project(vue version 3.2.31), #nonReactive wasn't updated. This's different from what I've seen in SFC
playground.

What you see there is normal. when one reactive dependency of the template changes, the whole component is re-> rendered, with all the latest data.

When I tested it in my project, I considered that all non-responsive data would not update the DOM ( like nonReactive in video )

@LinusBorg
Copy link
Member

Thanks for the video, but that doesn't tell me much without understanding how exactly to replicate it.

@xiexuan-star
Copy link
Author

https://github.com/xiexuan-star/issue-demo
You can clone it.
It is already late at night in my country, so I may not be able to reply to you in time

@LinusBorg

This comment has been hidden.

@xiexuan-star

This comment has been hidden.

@LinusBorg LinusBorg added feat: script-setup Related to experimental implementation of RFC #227 feature request New feature or request 🔩 p2-edge-case labels Apr 2, 2022
@LinusBorg
Copy link
Member

LinusBorg commented Apr 2, 2022

No I see what you mean. This is in fact a side-effect of the way script setup is compiled for dev. it essentially looks like this:

import { ref,shallowRef, defineComponent } from 'vue'

export default defineComponent({
  setup() {
    const foo = shallowRef({fooProp:1})
    const bar = ref(1);
    let nonReactive = 1
    function onClick(){
      foo.value.fooProp++;
      bar.value++;
      nonReactive++;
    }

    return {
      foo,
      bar,
      nonReactive // this will now forever be 1, as it reassigned a primitive value to an object property
    }
  }
})

Whereas in production/playground, it will look more like this:<script>
import { ref,shallowRef, defineComponent } from 'vue'

import { ref,shallowRef, defineComponent } from 'vue'

export default defineComponent({
  setup() {
    const foo = shallowRef({fooProp:1})
    const bar = ref(1);
    let nonReactive = 1
    function onClick(){
      foo.value.fooProp++;
      bar.value++;
      nonReactive++;
    }

    return () => {
      // render function directly accessing the above variables in its closure.
      // here, changes to `nonReactive` will be picked up when this render function is being re-run
    }
  }
})

So to summarize:

  1. The behavior is unrelated to shallowRef/shallowReactive
  2. The behavior in dev is due to the primitive value being reassinged to the setup function's return object.
  3. The pro version works because nonreactive is in the scope of the inlined render function.

This is surely something we could improve on.

@LinusBorg LinusBorg changed the title Some unexpected result in ShallowRef changes to nonreactive variables containing primitive values are reflected in prod, but not in dev. Apr 2, 2022
@xiexuan-star
Copy link
Author

Thank you for your patience. Now I understand the difference

@lidlanca
Copy link
Contributor

lidlanca commented Apr 3, 2022

@LinusBorg do you not consider different behavior between dev and prod build a bug?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat: script-setup Related to experimental implementation of RFC #227 🐞 bug Something isn't working 🔩 p2-edge-case
Projects
Next Patch
Dev/Prod Inconsistency
3 participants