Normalization in a setter for a public prop is not reactive, causing that sometimes the component doesn't get rehydrated when the parent component providing the original data changes the data.
https://playground.lwcjs.org/projects/JmtUCF4xd/4/edit
Note: look at the child's setter for items to reproduce the issue.
The implementation details of this is described here:
https://github.com/salesforce/lwc/pull/1038/commits/ea671e5b70153d1d6b839729a363fcbb11257a1d
And can now be implemented on master.
Another example of this broken in the wild is here: https://playground.lwcjs.org/projects/s1BXbEXLH/3/edit
Lighting datatable is using setters for normalization! :(
/cc @reiniergs @gonzalocordero
Seems that this can be worked around for now by moving normalization into the getter.
I've put together a simple(and common example) to illustrate the issue here:
https://playground.lwcjs.org/projects/4nz2Z8DfN/7/
This is certainly a problem.
@caridy and I had discussion yesterday about it, and at first I thought it'd be ok to just move the normalization into a separate function, but now I'm having second thoughts about it.
I'm not sure if we can just say "don't use setters for arrays and objects if you plan to normalize the incoming data", that's just confusing and kinda counter-intuitive. In my opinion, setters, are meant for doing things just like that. This pattern is also well spread all around our components, and re-factoring them would take some time. I don't feel comfortable for example, tackling an unplanned refactor for Datatable.
Anyways, I'd love for us to come up with a solution that satisfies everyone, we are here to support LWC, so whatever it's decided we will adapt, I just wanted to share my concerns.
Thanks!
cc:/ @jodarove @saw
We talked it at length as well, and there is no technical way we can support setters for objects or arrays since we can't track its mutations.
@kevinv11n is writing a doc with the details.
I don't know the technical details behind why this doesn't work, but it's certainly strange and confusing to have this limitation from a user perspective. Attributes values can be objects or arrays, but they can't be used for setters is a limitation that's hard to communicate, like @gonzalocordero said. Of course, the bigger problem is that this is just a big pile of work for us to take on
@saw there is no work for you guys, if what you have works, we are changing nothing on the engine, at least not until we don't have a performant solution which is unlikely.
All we are going to do is to document this thoroughly and potentially add some warnings at runtime.
@diervo yes they have to change the implementation if they are expecting to receive changing objects from their parent, e.g.: datatable, treeview, etc. Like the example above using the datatable, the consumer of it has no idea what's going on, and how to fix it.
we should probably have a meeting about this asap.
I have a proposal that my solve this issue, working on the formalization of it, will share it soon.
This issue is now half-way there. The underlying implementation is now ready for the reactive setters, and reactive wired methods. Here is a reference implementation for the reactive setters: https://github.com/salesforce/lwc/pull/1038/commits/ea671e5b70153d1d6b839729a363fcbb11257a1d
We are waiting for features flagging so we can introduce them slowly.
Most helpful comment
I have a proposal that my solve this issue, working on the formalization of it, will share it soon.