It's computed()
, but with a second argument that gets passed each newly returned value in order to produce a string cache key. If you return the same cache key as the previous run of the computed, no update will be performed (no effects, no renders, etc).
- computed(
- () => ['an', 'unstable', 'return', 'value'],
- )
+ computedWithMemo(
+ () => ['an', 'unstable', 'return', 'value'],
+ (value) => value.join(), // a stable return value
+ )
Here's a full example:
// create an array of todo list items that will change often
const todos = signal([]);
// create a computed signal for the array of items with .completed==true
// we only want this computed to update when _completed_ items change
const completed = computedWithMemo(
// this compute() function returns a new array every time:
() => events.value.filter(todo => todo.completed),
// but this getKey() returns a stable string cache key for compute() return value:
(value) => value.reduce((key, todo) => key + todo.id, ''),
);
// log every time the list of completed todos changes
effect(() => console.log(completed.value));
// This will *not* run the effect, because no completed items were added/removed:
todos.value = [{id:1, completed:false}];
// This *will* run the effect, because the filtered list of completed items produces a new string key:
todos.value = todos.value.concat({id:2, completed:true});