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.
Posting a follow up here based on an offline discussion.
This is a valid usage of the
@cachedutility from tracked-toolbox. The narrow use case meets the below requirements:outputgetter is expensive.outputis used multiple times in other getters in JS. (Ifthis.outputis only used directly in the template, it will already have exactly the same semantics around rerunning as it does with@cache.)outputgetter, using@cachewill not evaluate changes of the arguments' values, which means ifthis.args.bis set to the same value as before, theoutputgetter will still rerun. This is not a concern in this use case, because I know the parent will not set the same value in input args.