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

Perserve immutable semantic on accessing reactive object properties #5042

Closed
ycw opened this issue Dec 4, 2021 · 0 comments · Fixed by #5048
Closed

Perserve immutable semantic on accessing reactive object properties #5042

ycw opened this issue Dec 4, 2021 · 0 comments · Fixed by #5048
Labels
🐞 bug Something isn't working scope: reactivity

Comments

@ycw
Copy link

ycw commented Dec 4, 2021

What problem does this feature solve?

The Problem:

readonly() immutable semantic silently lost on accessing :

// ex. 1
const x = ref(0)
const o = reactive({ 
  x: readonly(x), 
  //.. other mutable props ..  
})
++o.x // 1   ( =mutable  )

We may use no-setter computed() instead but intention is less obvious :

// ex. 2
const x = ref(0)
const o = reactive({ 
  x : computed( () => x.value )
  // .. other mutable props .. 
})
++o.x // warnings: Write operation failed: computed value is readonly

Feature request:

Vue should preserve immutable semantic when users assign a readonly() ref to a reactive property ( ex.1 ) ; and show warnings when immutable reactive properties are being mutated ( as if ex.2 ) .

End user experience:

When we receive a object wrapped in reactive() from "parent component" ( or "inject from provider" or "Pinia store instance" )
we're now confident to mutate any properties as data providers are now able-to and supposed-to handle access control for all data they provided in the single reactive/ref.

With Volar, we can even get early errors.

// ex. consume a Pinia store, mutate a readonly ref immutWallet
import useMyStore from './stores/myStore.js'
const store = useMyStore()    //-> a reactive
const onClick = () => ++store.immutWallet   // Volar: Error: key 'immutWallet' is readonly. 

This feature may immediately solve vuejs/pinia#872 (comment)

What does the proposed API look like?

Code sample

Data providers setup access control for properties

const t = ref(0)   // global time for ex.
const el = ref()   // in-tmpl ref for ex.
onMounted(() => 
  provide( 'o', reactive({  
    t: readonly(t), 
    el 
  }) )
)
setInterval(() => ++t.value, 1000)

Data consumers try to access an immutable property

const o = inject( 'o' )
const onClick = () => {
  o.el.dataset.triggerAt = o.t      // get... ok
  o.t = 0     // set... will warn in web console
}
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
🐞 bug Something isn't working scope: reactivity
Projects
None yet
2 participants