Memos
Edit this pageMemos are a type of reactive value that can be used to memoize derived state or expensive computations. They are similar to derived signals in that they are reactive values that automatically re-evaluate when their dependencies change. However, unlike derived signals, memos are optimized to execute only once for each change in their dependencies.
Memos expose a read-only reactive value (like a signal) and track changes in their dependencies (similar to an effect). This makes them useful for caching the results of expensive or frequently accessed computations. By doing this, memos minimize unnecessary work within an application by retaining the results of a computation until its dependencies change.
Using memos
A memo is created using the createMemo
function.
Within this function, you can define the derived value or computations you wish to memoize.
When called, createMemo
will return a getter function that reads the current value of the memo:
While memos look similar to effects, they are different in that they return a value. This value is the result of the computation or derived state that you wish to memoize.
Advantages of using memos
While you can use a derived signal to achieve similar results, memos offer distinct advantages:
- Memos are optimized to execute only once for each change in their dependencies.
- When working with expensive computations, memos can be used to cache the results so they are not recomputed unnecessarily.
- A memo will only recompute when its dependencies change, and will not trigger subsequent updates (as determiend by
===
or strict equality) if its dependencies change but its value remains the same. - Any signal or memo accessed within a memo's function is tracked. This means that the memo will re-evaluate automatically when these dependencies change.
Memo vs. effect
Both memos and effects are important when managing reactive computations and side effects. They, however, serve different purposes and each have their own unique behaviors.
Memos | Effects | |
---|---|---|
Return value | Yes - returns a getter for the result of the computation or derived state. | Does not return a value but executes a block of code in response to changes. |
Caches results | Yes | No |
Behavior | Function argument should be pure without reactive side effects. | Function argument can cause side effects like UI updates or data fetches. |
Dependency tracking. | Yes | Yes |
Example use cases | Transforming data structures, computing aggregated values, derived state, or other expensive computations. | UI updates, network requests, or external integrations. |
Best practices
Pure functions
When working with memos, it is recommended that you leave them "pure".
A pure function is one that does not cause any side effects. This means that the function's output should solely depend on its inputs.
When you introduce side effects into a memo, it can complicate the reactivity chain. This can lead to unexpected behavior, such as infinite loops, that lead your application to crash.
These infinite loops can be triggered when a memo has a side effect that causes its dependencies to change. This will cause the memo to re-evaluate, which will then trigger the side effect again, and so on until the application crashes.
This can be avoided by using a createEffect
to handle the side effects instead:
Here, the createEffect
will handle the side effects, while the isEven
memo will remain pure.
Keep logic in memos
Memos are optimized to execute only once for each change in their dependencies. This means that you can remove unnecessary effects that are triggered by a memo's dependencies.
When working with derived state, memos are the recommended approach over effects. Keeping the logic in a memo prevents unnecessary re-renders that can occur when using an effect. Similarly, effects are better suited to handle side effects, such as DOM updates, rather than derived state. This separation of concerns can help keep your code clean and easy to understand.