Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can 5.x | Reflect.updateDeep doesn't deep update into list members #5513

Open
rjgotten opened this issue Nov 24, 2020 · 0 comments
Open

Can 5.x | Reflect.updateDeep doesn't deep update into list members #5513

rjgotten opened this issue Nov 24, 2020 · 0 comments
Assignees

Comments

@rjgotten
Copy link

rjgotten commented Nov 24, 2020

Assume the following model definitions and data:

const Item = DefineMap.extend({
 id : { type : "string", identity : "true" },
 value : { type : "string" }
});

const Root = DefineMap.extend({
  items : { Type : [ Item ]}
});

const root = new Root({
  items : [{ id : "1", value : "original" }]
});

Use Reflect.updateDeep to update with new data, like so:

Reflect.updateDeep( root, {
  items : [{ id : "1", value : "changed" }, { id : "2", value : "added" }]
});

Expected value for root

[{ id : "1", value : "changed" }, { id : "2", value : "added" }]

Actual value for root

[{ id : "1", value : "original" }, { id : "2", value : "added" }]

The root cause is in DefineList which implements the can.updateDeep symbol by aliasing to this.replace.
The latter does a shallow update based on can-diff key diffs and does not deep update the entities in the list.

It seems there is an assumption that updates will always flow through a centralized constructor-store behavior from can-connect, where it would have taken care to update the entities.

That assumption is imho false.
There are reasons to attach identity keys to entities that don't flow through such a behavior.

For instance;
A particular entity serving as a member of a list may only ever be fetched as part of a greater object graph where its 'parent' entity is the only one with a can-connect pipeline attached to it. But you still want to give that member entity an identity to minimize dom churn when rendering it with a {{#for (of)}} stache helper.

Proposed solution
Update either the replace method or the can.updateDeep symbol implementation on DefineList.
Neither really does what it says on the tin.
The deep update is definitely not deep. And the list members are not replaced; i.e. are not updated to the point where their new state looks like they were fully replaced.

@rjgotten rjgotten changed the title Can 5.33.x | Reflect.updateDeep doesn't deep update into list members Can 5.x | Reflect.updateDeep doesn't deep update into list members Nov 24, 2020
@cherifGsoul cherifGsoul self-assigned this Dec 30, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants