ember-deep-tracked icon indicating copy to clipboard operation
ember-deep-tracked copied to clipboard

Issues with accessing the store from a deep-tracked object

Open spuxx-dev opened this issue 3 years ago • 4 comments

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).

spuxx-dev avatar Oct 15 '21 14:10 spuxx-dev

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:

  1. An object is created and is then "autotracked" by Ember (Not 100% sure of this) in some way might be something else.
  2. When a function is called on a car the function retains the calling context.
  3. Thus the store in changeColor is the correct store and not a Proxy of the store.

When calling with @tracked we get this:

  1. An object is created and tracked outside of Ember (Not 100% sure of this).
  2. When a function is called on a car the function does not retain the calling context.
  3. 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/

Alonski avatar Oct 23 '21 17:10 Alonski

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?

spuxx-dev avatar Oct 23 '21 17:10 spuxx-dev

@NullVoxPopuli I am having a hard time figuring out how to recreate this issue in a Unit test. Would like help please :)

Alonski avatar Oct 25 '21 06:10 Alonski

Where did you get stuck? What code have you tried so far?

NullVoxPopuli avatar Oct 25 '21 11:10 NullVoxPopuli