glimmer.js

Glimmer child component does not re-render when the parent passes it a different argument


To be more explicit, the child component creates a property which is dependent on the argument passed by the parent component. I am not using the parent argument directly in the child template (this case works just fine).

Coming from a React background, my mental model suggests new arguments passed to a component will trigger re-render. But I am aware Glimmer does things differently with its @tracked decorator.

Okay, here is the contrived example. For a demo, head to the Glimmer Playground.

// parent-template.hbs
<button onclick={{action doubleNumber}}>Double Number</button>
<div>
  Parent - {{number}}
</div>

<Child @number={{number}} />
// parent-component.ts
import Component, { tracked } from '@glimmer/component';

export default class extends Component {
  @tracked number = 2;

  doubleNumber() {
    this.number = this.number * 2;
  }
}
// child-template.ts
<div>
  Child will render double of parent {{doubleOfParent}}
</div>
// child-component.ts
import Component, { tracked } from "@glimmer/component";

export default class extends Component {
  args: {
    number: number;
  }

  get doubleOfParent () {
    return 2 * this.args.number;
  }
};

Here the parent displays the doubled number on every click of the button. But the child never re-renders?

My question is do we always need to have the tracked variable inside the template. In this case number. And express the child template like this

<div>
  Child will render double of parent {{double @number}}
</div>

Here double is helper which doubles the number.

If it is so what is the reason behind having the tracked properties/argument in the template?


Solution

  • It looks like your doubleOfParent() method is missing a @tracked annotation since its output depends on the args property:

    import Component, { tracked } from "@glimmer/component";
    
    export default class extends Component {
      args: {
        number: number;
      }
    
      @tracked('args')
      get doubleOfParent() {
        return 2 * this.args.number;
      }
    };
    

    you can find more information on this topic at https://glimmerjs.com/guides/tracked-properties