ember-deep-tracked
ember-deep-tracked copied to clipboard
Issues with accessing the store from a deep-tracked object
There is an issue with accessing the ember-data store from an object if that object is being kept in a deep-tracked array. A minimal example to reproduce the behavior can be found here: https://github.com/LeopoldHock/ember-deep-tracked-test
The core issue
Say we have a custom object that can make use of service injection by having its owner set in the constructor method.
export default class Car {
@service store;
constructor(owner) {
setOwner(this, owner);
}
}
And after instantiation, that object will be put into a nested deep-tracked context.
// e.g. in a service
import { tracked } from 'ember-deep-tracked';
@tracked data = {
cars = []
}
let car = new Car(this);
data.cars.push(car);
And at some point, that object attempts to access the injected store to find a record.
// in car.js
let someRecord = this.store.peekRecord("my-collection", "some-key");
someRecord
will be null, while requesting the same record in a different contect (e.g. a service) will return the record.
The issue does not occur in a non-tracked context (e.g. by simply removing @tracked).
I think that this isn't necessarily a bug but an incorrect usage of tracked.
From my understand what happens when @tracked
isn't applied is this:
- An object is created and is then "autotracked" by Ember (Not 100% sure of this) in some way might be something else.
- When a function is called on a car the function retains the calling context.
- Thus the store in
changeColor
is the correct store and not a Proxy of the store.
When calling with @tracked
we get this:
- An object is created and tracked outside of Ember (Not 100% sure of this).
- When a function is called on a car the function does not retain the calling context.
- Thus the store in
changeColor
is now not the correct store. It is now a Proxy of the store (Not sure why).
Decorating changeColor
with @action
forces Ember to maintain the context correctly:
https://github.com/Alonski/ember-deep-tracked-test/commit/7a2f0174d38d0f39d32626f8953c4305759416c3
And not sure if this will work but: https://alonski-leopoldhock-ember-deep-tracked-test-g4xjjvpcwgrv.github.dev/
I'd argue that getting a "different" version of a singleton is not expected behavior when injecting a service, so I'd definitely consider this a bug. I'll also add that simply switching to https://github.com/tracked-tools/tracked-built-ins for tracking the object will result in the expected behavior - fully functional tracking and access to the "correct" store.
However, using @action is at least a good workaround. I didn't think of that!
/ Can you elaborate on the last point? 3. Thus the store in changeColor is now not the correct store. It is now a Proxy of the store (Not sure why). What woud that Proxy be used for? In what situation would it be desirable to get a proxy of the store, not the actual store?
@NullVoxPopuli I am having a hard time figuring out how to recreate this issue in a Unit test. Would like help please :)
Where did you get stuck? What code have you tried so far?