tezvyn:

How would you implement a memoized selector for expensive derived state?

AI-drafted, machine-checkedSource: ngrx.iointermediate

It tests cache invalidation and pure functions for reactive derived state. A strong answer covers reference tracking on inputs, returning cached results when unchanged, and requiring immutable or stable arguments.

WHAT THIS TESTS: This question probes whether you understand how to avoid redundant computation in reactive state management. Interviewers want to see that you know derived state should be computed lazily and only when its dependencies change, not on every render or store update. They are looking for awareness of referential equality, immutability, and the difference between a simple computed property and a memoized selector that handles expensive logic.

A GOOD ANSWER COVERS: First, define a selector as a pure function that takes state slices as arguments and produces derived output. Second, explain that the selector must keep a cache of the last inputs and the last output. On each call, it compares the new inputs to the cached inputs using reference equality for objects or strict equality for primitives. If they match, it returns the cached output immediately. If they differ, it recomputes, stores the new inputs and output, and then returns the result. Third, emphasize that the input functions themselves must be pure and deterministic so that the same inputs always yield the same output. Fourth, state that the source state passed into the selector must be immutable or at least updated with new references when changed; if you mutate an object in place and pass it back, the reference check will pass and the selector will return stale data. Fifth, mention that in frameworks like NgRx with Reselect, or Pinia with computed properties, or Svelte with derived stores, this pattern is built in but relies on the same contract.

COMMON WRONG ANSWERS: A major red flag is suggesting that you store the computed value in a component variable and update it manually inside a lifecycle hook or an effect. This misses the centralized, reusable nature of selectors. Another mistake is claiming that deep equality checks on large objects are fine for memoization; deep comparisons can be slower than the original computation and defeat the purpose. Some candidates also forget that selector inputs must be stable; if you pass a new array literal or inline object on every call, the cache will never hit and memoization is useless.

LIKELY FOLLOW-UPS: The interviewer might ask how you would handle parameterized selectors where the argument is a dynamic filter string or an ID. They could also ask about memory leaks from long-lived caches or how to implement a selector with multiple levels of composition. Another angle is asking how signals in Angular or runes in Svelte change the memoization story compared to traditional observable stores.

ONE CONCRETE EXAMPLE: Imagine an e-commerce cart with one thousand items and a selector that calculates the discounted total after applying a complex coupon algorithm. Without memoization, every tiny store update such as toggling a UI flag would trigger an O of n recomputation. With a memoized selector, the function only recomputes when the cart items array reference or the coupon code changes. If the user merely opens a modal, the selector returns the previously cached total in O of one time because the input references are unchanged. This only works because the cart state is updated immutably; pushing to the existing array would break the cache.

Read the original → ngrx.io

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.