Recently I encountered an use case of @cached
from tracked-toolbox when writing a Glimmer component with autotracking. Here is an example code snippet:
import Component from '@glimmer/component';
/**
* Example usage
* <PersonInfo
* @a={{this.objA}}
* @b={{this.stringB}}
* @c={{this.intC}}
* />
* Where objA can be a large object
*/
export default class PersonInfo extends Component {
/**
* I hope @cached here can help avoid re-running output getter in each
* of the other getters, e.g. this.msg, this.link, this.name
* But whenever any input args changes it triggers update
* (i.e. parent run this.objA = newObj)
*/
get output() {
return someExpensiveLogic(this.args.a, this.args.b, this.args.c);
}
get msg() {
return translate(this.output.msg);
}
get link() {
return convert(this.output.link);
}
get name() {
return change(this.output.name);
}
}
{{!-- In the template --}}
<div>
{{this.name}}
{{this.msg}}
{{this.link}}
</div>
Without using @cached
, the above code will execute the output
getter 3 times when rendering, once for each of msg
, link
and name
.
I also thought about building my own cache for output
, but it requires me to manually keep track of which state is used and hash them, which could be expensive and hard to maintain.
From my understanding, what @cached
provides is an access to the "global tag" in the auto tracking system, so I can rely on that tag to determine when the cache needs refresh.
Since this is not supported in a company project I work on for now, I hope this usage it can encourage us to add such support later.
Note: I found that @cached
is convenient wrapper of
import { createCache, getValue } from '@glimmer/tracking/primitives/cache';
So fundamentally what I need is @glimmer/tracking/primitives/cache
.