EventTarget instances cannot be made reactive.
Vue version
3.2.45
Link to minimal reproduction
Steps to reproduce
- Create a class that extends
EventTarget
.
class SubClass extends EventTarget {};
- Instantiate that class and make it reactive.
const subClass = reactive(new SubClass());
- Check if it is reactive using
isReactive
.
isReactive(subClass); // false
Further testing shows that without the class syntax sugar the line that breaks reactivity for that class is:
SubClass.prototype = Object.create(EventTarget.prototype);
What is expected?
The expected result is that the instance will become reactive.
What is actually happening?
The instance does not become reactive.
System Info
No response
Any additional comments?
Some libraries provide instances extended from EventTarget
so it would be good to know why they cannot be made reactive and if there is a way around it.
We only make plain objects to reactive and it seems no workaround.
Object.prototype.toString.call(new SubClass()) // '[object EventTarget]' not '[object Object]'
Because when reactive proxies, it will judge the incoming value, and the current incoming object type is [object EventTarget] ,not within the scope of reactive proxy
function targetTypeMap(rawType: string) { switch (rawType) { case 'Object': case 'Array': return TargetType.COMMON case 'Map': case 'Set': case 'WeakMap': case 'WeakSet': return TargetType.COLLECTION default: return TargetType.INVALID } } The object type you pass in is ultimately judged as TargetType.INVALID ,reactive would return the instance itself
class SubClass extends EventTarget {} const obj = new SubClass() const subClass = reactive(obj); const isSubClassReactive = isReactive(subClass); console.log(obj === subClass); // true
Some libraries provide instances extended from EventTarget so it would be good to know why they cannot be made reactive and if there is a way around it.
The general recommendation is to not make complex class constructs reactive. We also don't want to add more complexity into the reactivity internals by supporting arbitrary native object types such as Element, Node, EventTarget etc. and then have to work around potential issues with those (i.e.: if we made Element
reactive you would quickly end up with a max Call Stack exceeded error as any element could provide a circular path through the whole document tree)
Reactive state is optimally done with POJOs exclusively (plus the officially supported collection types).