Dynamically set reactive nested property is different when set during initialization
Version
3.2.22
Reproduction link
Steps to reproduce
- Run repro
What is expected?
Both isReactive()
should yield the same result
What is actually happening?
Setting a nested reactive()
object dynamically is different from initialiazing it: reactive({ nested })
I found this in Pinia, where the following code doesn't work:
import { ref, reactive } from 'vue'
import { storeToRefs } from 'pinia'
const useTest = defineStore('test', () => {
const foo = ref('foo')
const bar = reactive({
baz: 'something'
}
return {
foo, bar
}
}
const store = useTest()
const { foo, bar } = storeToRefs(store)
// bar.value is undefined
This is because pinia stores are reactive()
objects that have their properties set dynamically (for various reasons like cross store usage and HMR).
storeToRefs()
code is
export function storeToRefs(store) {
store = toRaw(store) // avoid triggering getters
const refs = {}
for (const key in store) {
const value = store[key]
if (isRef(value) || isReactive(value)) {
refs[key] = toRef(store, key)
}
}
return refs
}
I'd say that this is expected. the raw source object for the first store does contain a proxy as its nested
property because you defined it that way.
Would you expect toRaw()
to somehow unwrap that? that would alter the source object.
I would expect to both reactive({ nested })
and reactive({}).nested = nested
to work the same way with nested = reactive({})
🤔
I can do toRaw(store).nested = nested
though but it won't be observed (which is intentional with toRaw()
) so that would be problematic
But I see what you mean: reactive({}).nested = ...
isn't affecting the original object...
Maybe it's reasonable needing to change it this way