Still experimenting things with Aurelia Store and immerjs. I have a component which receive an article object so it can display it. This article comes from the store. On the component, there is a button to mark the article as read. When it is clicked, an action is dispatched to mark the article as read (API request + change in the store). When I try to update the article in the store with:
export const markedAsRead = produce((draft: IState, article: IArticle) => {
// If we access article directly, immerjs has no knowledge of the modification and the state is mutated.
const index = articles.map((article) => article.id).indexOf(articleToFind.id);
draft.rss.unreadArticles[index].isRead = true;
});
I get this error: Unhandled rejection Error: Immer drafts cannot have computed properties
. If I test with an object that is not passed to a view model, it works fine (for instance by putting the code below in the constructor of the App
class):
const originalArticle = new Article({status: null});
const baseState = {articles: [originalArticle]};
const nextState = produce(baseState, (draft) => {
const index = draft.articles.map((article) => article.id).indexOf(originalArticle.id);
const article = draft.articles[index];
article.status = 'Read';
});
console.log(nextState.articles[0]);
console.log(originalArticle);
From what I was able to track down, it comes from the fact that Aurelia defined getters and setters on objects for each properties. Because of that, immerjs canāt clone the objects and thus canāt work. From what I read here, it actually makes sense from the immerjs perspective:
The problem with getters is that they canāt be cloned. What should be cloned? The value? But in that case they become āstaticā. Or should the descriptor be copied? But in that case the closure of the getter might be wrong, that is, referring to something it was already referring to, there is no way to tellā¦
Any thoughts on this? I guess I can always revert to the spread operator but it feels like defeating the point of immerjs.