# How to force re-render a Glimmer component

**URL:** <https://discuss.emberjs.com/t/how-to-force-re-render-a-glimmer-component/18150>\
**Category:** Questions\
**Created:** [August 22, 2020, 11:25am UTC](https://discuss.emberjs.com/t/how-to-force-re-render-a-glimmer-component/18150 "2020-08-22T11:25:25Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![mupkoo](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/mupkoo/32/16373_2.png) [@mupkoo](https://discuss.emberjs.com/u/mupkoo)\
**Post date:** [August 22, 2020, 11:25am UTC](https://discuss.emberjs.com/t/how-to-force-re-render-a-glimmer-component/18150/1 "2020-08-22T11:25:25Z")

</div>

Hello 👋 ,

Is there a way to force re-render a Glimmer component?

What I have is an `Image` component, which displays a placeholder image, while the actual one is being downloaded, which later gets replaced by it. The fetch of the image is triggered by a `{{did-insert}}` action.

This is all ok, but since I am relying on that hook, I have to do some manual work when the passed image is changed. A re-render will solve this.

Here is a solution that I came up with

```nohighlight
{{#each (array this.photo) key="path" as |photo|}}
  <Image @photo={{photo}} />
{{/each}}

```

This works really well, but it feels hacky. I wonder if there is a built in way to do it.

---

<div class="post-metadata">

**Author:** ![chriskrycho](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/chriskrycho/32/17763_2.png) [@chriskrycho](https://discuss.emberjs.com/u/chriskrycho)\
**Post date:** [August 22, 2020, 3:21pm UTC](https://discuss.emberjs.com/t/how-to-force-re-render-a-glimmer-component/18150/2 "2020-08-22T15:21:47Z")

</div>

This is a really common challenge people have as they learn Octane idioms and Glimmer Components, so I’m glad you asked it!

The key here is moving away from the_imperative_ mode we tended to reach for in Ember Classic, where we would respond to a lifecycle hook or event by telling the app “create some new state” or “update in this way” and moving to a more truly one-way data flow paradigm. You can think of this as really going all in on Data Down, Actions Up. That means we need to transform your approach with `did-insert` into something that defines everything in terms of _data_.

To get there, we need to define what the template renders purely in terms of data derived from the arguments to the component. The result might look something like this:

```nohighlight
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';

const PLACEHOLDER_URL = '...';
const FAILED_URL = '...';

class ImageData {
  @tracked state = 'loading';
  @tracked value;
  @tracked reason;
}

export default class Image extends Component {
  get imageData() {
    let data = new ImageData();
    let { url } = this.args.photo;

    fetch(url)
      .then(() => {
        data.state = 'loaded';
        data.value = url;
      })
      .catch((reason) => {
        data.state = 'error';
        data.reason = reason;
      });

    return data;
  }

  get src() {
    switch (this.imageData.state) {
      case 'loaded':
        return this.imageData.value;
      case 'loading':
        return PLACEHOLDER_URL;
      case 'error':
        return FAILED_URL;
    }
  }
}

```

Here’s the corresponding template (yours might be more complicated, of course):

```handlebars
<img src={{this.src}} alt={{@photo.alt}} />

```

Note that in `src`, we use `imageData` to determine what to show, and `imageData` uses `args` to determine what to load. Since we’re using `src` in our template, any time the `photo` argument to `Image` changes (or, if it has internal tracked properties for `src` and `alt` and either of _those_ change) it’ll update correctly!

(If it’s surprising that we’re doing an async data lookup in a getter, which is often treated as an antipattern, see [this discussion on “Guidance re: triggering tasks from component args”](https://discuss.emberjs.com/t/guidance-re-triggering-tasks-from-component-args/18052).)

This pattern comes up enough that my team actually built a [`load` helper and `AsyncData` type](https://gist.github.com/chriskrycho/306a82990dd82203073272e055df5cd1) to make it convenient, which can be used on either the JS or Handlebars side. Using that, this would be the whole implementation of the backing class:

```nohighlight
import Component from '@glimmer/component';
import { load } from 'my-app/helpers/load';

const PLACEHOLDER_URL = '...';
const FAILED_URL = '...';

export default class Image extends Component {
  get imageData() {
    let { url } = this.args.photo;
    let promise = fetch(url).then(() => url);

    return load(promise);
  }

  get src() {
    switch (this.imageData.state) {
      case 'loaded':
        return this.imageData.value;
      case 'loading':
        return PLACEHOLDER_URL;
      case 'error':
        return FAILED_URL;
    }
  }
}

```

The template would be exactly the same!

The big takeaways here:

1. There’s no need for `did-insert` in the template anymore! All the template needs to know is what `src` to use for the `img` tag, and that’s just computed as data by the class.
2. We now have 100% 1-way data flow. Arguments come into the component, and it updates automatically just by using auto-tracking. (You would get the same effect from VDOM implementations in other frameworks, but the performance tradeoffs would be different.)
3. Everything in this approach—including the async operation!—is just data. We’ve managed to describe the whole component flow in terms of _one source of truth_ (or “root state”): the `photo` argument to the component. The two other pieces of data are _derived_ from that source of truth (so they’re “derived state”).

* * *

If you’re curious about the `load` helper and `AsyncData` type, I posted an example this week of using it to [migrate away from `PromiseProxyMixin`](https://v5.chriskrycho.com/journal/migrating-off-of-promiseproxymixin-in-ember-octane/), I’ll be writing up an explanation of the _philosophy_ behind it—which is basically just taking the ideas from this example and expanding them into something more general-purpose—this coming work week, and I’ll post a link to that on this forum when it’s live!

---

<div class="post-metadata">

**Author:** ![mupkoo](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/mupkoo/32/16373_2.png) [@mupkoo](https://discuss.emberjs.com/u/mupkoo)\
**Post date:** [August 23, 2020, 7:05am UTC](https://discuss.emberjs.com/t/how-to-force-re-render-a-glimmer-component/18150/3 "2020-08-23T07:05:35Z")

</div>

Thank you for the reply. This pattern looks nice. I usually go with a simpler approach, but always felt that I was kinda cheating.

```javascript
@tracked fetchedSrc;

get src() {
  if (this.fetchedSrc !== this.args.photo.url) {
    this.fetchImage(this.args.photo.url);
    return this.placeholdeSrc;
  } else {
    return this.fetchedSrc;
  }
}

async fetchImage(url) {
  await fetch(url);
  this.fetchedSrc = url;
}

```

The problem that I have, is that I am not just changing the src of the `img` tag, but the width and height as well, depending on the actual image sizes. This results in a slight visual resize of the previous source, before it actually changes to the new one. Which is solved by doing a complete re-render.

Thanks again for the reply. I will definitely check the references that you gave.

* * *

A bit unrelated - I did not know that you can use `fetch` to fetch an image 😮. Which lead me to a new discovery for me - `AbortController` (double 😮).

---

<div class="post-metadata">

**Author:** ![chriskrycho](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/chriskrycho/32/17763_2.png) [@chriskrycho](https://discuss.emberjs.com/u/chriskrycho)\
**Post date:** [August 23, 2020, 5:29pm UTC](https://discuss.emberjs.com/t/how-to-force-re-render-a-glimmer-component/18150/4 "2020-08-23T17:29:13Z")

</div>

Two notes there:

- the solution I gave would handle that, because it would switch back to the loading state when given a new argument
- you could define the height and width as getters dependent on the resolved image result as well, which would prevent their ever being applied to the wrong image

Also, you likely don’t need the previous image to be tracked!

---

<div class="post-metadata">

**Author:** ![mupkoo](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/mupkoo/32/16373_2.png) [@mupkoo](https://discuss.emberjs.com/u/mupkoo)\
**Post date:** [August 24, 2020, 11:37am UTC](https://discuss.emberjs.com/t/how-to-force-re-render-a-glimmer-component/18150/5 "2020-08-24T11:37:21Z")

</div>

I would definetly play with this a bit to see the result that it produces.

> [@chriskrycho](#):
>
> Also, you likely don’t need the previous image to be tracked!

I will need to look into this, as I am not really sure when do getters get invalidated. For example, will the `get src()` get called again if the `this.args.photo.alt` changes?

---

<div class="post-metadata">

**Author:** ![chriskrycho](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/chriskrycho/32/17763_2.png) [@chriskrycho](https://discuss.emberjs.com/u/chriskrycho)\
**Post date:** [August 24, 2020, 1:19pm UTC](https://discuss.emberjs.com/t/how-to-force-re-render-a-glimmer-component/18150/6 "2020-08-24T13:19:29Z")

</div>

It will if `args.photo` changes _or_ if the `alt` property itself is tracked.

Also, it is not that the getter “invalidates.” There’s actually no magic around getters. They’re just plain JS getters, unlike in the old computed property world. By setting up getters you’re creating lazy references to access the other data in the system. They’ll be re-executed whenever a primitive that hooks into the VM’s tracking mechanics—currently just templates but soon also helpers on the JS side—consumes a tracked value either directly or by the lazy reference to it via the getter. But the only things that matter for tracking to work this way are the root tracked properties and the tracking-connected things which consume them either directly or indirectly.
