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.