Computed property is not updated when computed on object's property


#1

I think I have found a bug on computed property. I have a component my-cell, responsible for render 1 event.

Please take a look at my component/my-cell.js

export default Ember.Component.extend({ 
    isHighlighted: Ember.computed('highlight', 'event.createdAt', function() {
        //set highlight to true if event.createdAt has the same time as highlight time
    }
});

When isHighlighted is called, I put a breakpoint there, I found that this.get('event.createdAt') returns undefined. To be more informative, event is an object from data store. So this.get('event') would get me the event, but all properties of event are undefined.

When the page is finished loading, by Ember Inspector, event.createdAt is not undefined anymore.

I suspect my problem is because Ember will not load the whole object with its property into component.

How do I get around this? Is my approach right or not? Please point me out if I made any mistakes. Thank you.


#2

Hi @Jeffrey_Cheung,

I don’t consider this a bug. When you declare event.createdAt as a dependent of your computed property, Ember will set up two observers, one for the event binding itself, another for the createdAt value of event.

What I’m guessing happens is that since event is an Ember Data record it might not be fully resolved by the time the computed property runs the first time. I suggest using getWithDefault or checking if createdAt and returning false.

Something’s worrying me though:

This makes it both sound like you’re using a computed property as an observer, and that you’ll create an endless look, because you’re setting highlight from inside the computed property, which will trigger the computed property, which will make it set highlight which triggers the compu— you get my drift :stuck_out_tongue:

If the above is a correct assessment I suggest hooking into didInsertElement instead:

export default Ember.Component.extend({
  isHighlighted: false,

  didInsertElement() {
    this._super(...arguments);
    // calculate `value`
    this.set('highlight', value);
  }
});

Let me know if that any of that works, good luck!


#3

Hi @locks! Thank you for your reply.

Using a hook to do this task is a much cleaner solution. However didInsertElement hook is not the correct one. When this hook is called, this.get('event.createdAt') returns undefined.

The hook didReceiveAttrs works for me. This hook is called twice. The first time it called, this.get('event.createdAt') returns undefined, but when it called second time, I get my this.get('event.createdAt').

I also tried the hook didRender. It also works, and it is called 3 times. However I get the following warning: DEPRECATION: A property of X was modified inside the didUpdate hook. You should never change properties on components, services or models during didUpdate because it causes significant performance degradation. [deprecation id: ember-views.dispatching-modify-property]

It sounds weird to me because I did not call any didUpdate hook in my code. Maybe Ember is messing up didRender with didUpdate. But why changing properties on components, services or models during didUpdate with cause significant performance degradation?

In the Ember guide, it says

Setting properties on the component in didInsertElement() triggers a re-render, and for performance reasons, is not allowed.

So I cannot set properties wherever I want. but only in didReceiveAttrs. I guess.

Please share me your thought about this. I am a bit confuse at the moment. Thanks.:joy: