immer: Why can't drafts have computed properties?
Using immer v1.9.0+ with VueJS gives error ‘Immer drafts cannot have computed properties’
- Issue: _______
- Version: 1.9.0 onwards
- Expected behavior: Updating state using immer produce function runs without errors.
- Observed behavior: Immer (1.9.0+), when used with VueJS (2.5.0+) throws an error ‘Immer drafts cannot have computed properties’ while updating the state.
On further analysis, it looks like - Vue JS sets getters in all properties used in its components by default. And when we looked at the source of immer, we found that, below code throws error once it encounters a getter on any prop while making a shallow copy.
Immer is an awesome library and we want to continue using the same, but this issue is blocking us. Could you please explain the rationale behind below change and let us know how we can help to fix this issue ?
export function shallowCopy(base, invokeGetters = false) {
if (Array.isArray(base)) return base.slice()
const clone = Object.create(Object.getPrototypeOf(base))
ownKeys(base).forEach(key => {
if (key === DRAFT_STATE) {
return // Never copy over draft state.
}
const desc = Object.getOwnPropertyDescriptor(base, key)
if (desc.get) {
if (!invokeGetters) {
throw new Error("Immer drafts cannot have computed properties")
}
desc.value = desc.get.call(base)
}
if (desc.enumerable) {
clone[key] = desc.value
} else {
Object.defineProperty(clone, key, {
value: desc.value,
writable: true,
configurable: true
})
}
})
return clone
}
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 3
- Comments: 16 (4 by maintainers)
Pardon my naivety: could getters be skipped rather than cloned?
I’m wondering if this is a necessary design choice, or one built for maximum defensiveness that also happens to preclude otherwise workable systems.