The E
The E

Reputation: 747

Why is this Ember component created twice?

So really I'm just trying to decipher how Ember works here.

So I have ComponentOne. Which has propertyA (boolean) and property2 (array). If propertyA === true, the template will render and instance ComponentTwo for each member of propertyB:

{{#if propertyA}}
  {{#each propertyB as |collection]}}
    {{ComponentTwo data=collection}}
  {{/each}}
{{/if}}

While working with this we discovered an issue where an event handler in ComponentTwo was not running, even though we could verify the event was firing. This was happening in a situation where propertyA === true and propertyB.length === 1.

Through some judicious breakpoints and logging to the console, I was able to determine that this was happening in this sequence:

  1. an instance of ComponentTwo is created
  2. A second instance of ComponentTwo is created, using the same object for data.
  3. The first instance created in step 1 is destroyed.

The theory is that this is messing up the event handler because that handler was set in ComponentTwo.init() and removed in ComponentTwo.willDestroy(). Eventer being a singleton, it removes it for both instances of the component.

So my question is why would Ember create two instance at all? There's only one member of the array it's iterating.

Upvotes: 1

Views: 252

Answers (1)

You're doing something that causes the component to rerender.

Maybe you're toggling the boolean property twice.

Maybe you're mutating or replacing the array.

When the array is updated, Ember does not know which of the already rendered items correspond to which element of the new array, so it has to rerender everything, which would result in components being reinstantiated.

You can use the key parameter to let Ember recognize items even when the array changes.

To do this, each item in the array needs to be an object, e. g.:

propertyA: true,
propertyB: [
  {
    id: 'foo',
    collection: [], // whatever you used to have there
  },
  {
    id: 'bar',
    collection: [], // whatever you used to have there
  },
],

Now you can use the id property as the key like this:

{{#if propertyA}}
  {{#each propertyB key="id" as |collection]}}
    {{ComponentTwo data=collection}}
  {{/each}}
{{/if}}

Upvotes: 1

Related Questions