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

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 was marked as resolved.

@xiexuan-star

This comment was marked as resolved.

@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?

@LinusBorg LinusBorg added 🐞 bug Something isn't working and removed ✨ feature request New feature or request labels Apr 3, 2022
@yyx990803 yyx990803 added this to Dev/Prod Inconsistency in Next Patch May 10, 2022
chrislone pushed a commit to chrislone/core that referenced this issue Feb 4, 2023
zhangzhonghe pushed a commit to zhangzhonghe/core that referenced this issue Apr 12, 2023
@github-actions github-actions bot locked and limited conversation to collaborators Sep 18, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
Next Patch
Dev/Prod Inconsistency
3 participants