In a component framework, what does deriving a value from state during render mean, and why is it the default?
answer
- one source of truth
- recompute, do not maintain
- a cache can disagree; a computation cannot
- nothing to invalidate
- shrink the input before caching
basics
~20 sDeriving means recomputing the value from current state on each render and storing nothing. It is the default because a recomputed value cannot disagree with its inputs; a cache is an optimisation for where it measurably pays.
solid answer
~40 sA derived value is one computed from state the component can already read: a total, a filtered collection, a label, a `canSubmit` flag. Deriving it means evaluating that computation where the value is needed rather than keeping a second copy. It is the default for a correctness reason, not a style reason: a value recomputed from current state cannot be stale, there is nothing to invalidate, and the rule sits next to its use. The work is also usually trivial next to the render it happens inside. A cache is worth adding when the derivation is genuinely heavy — sorting or grouping thousands of records, building an index — and even then I would first try to shrink the input, because that removes the cost instead of adding a cache to manage.
go deeper
Recall the definition: a derived value is computed from state, not stored alongside it. Be able to name two examples, such as a total from a list and a submit-enabled flag.
Explain the mechanics: which unit re-evaluates, why the computation is small next to the render containing it, and what a cache adds in exchange for skipping it.
Show judgment about when to leave the default, and demonstrate that you narrow the input before reaching for a cache. Name the measurement that justified the change.
Frame it as a team default: computing is correct by construction, so caching should require a stated reason. Say how you keep that from becoming folklore in either direction.
A **derived value** is a value computed from other values a component can already read: a total from a list of items, a filtered collection from a collection plus a search term, a label from a status field, a boolean saying whether a form may be submitted. **Deriving** it means writing that computation and evaluating it where the value is needed, from the state as it is at that moment. Nothing extra is stored, so nothing has to be kept in step. ## Why recomputation is the default Every component framework re-evaluates *some* unit of work when the state it reads changes: a whole component function, a template expression, a compiled update block. Whatever that unit is, an expression inside it that reads state is re-evaluated with the new state at no extra cost to you. That buys the properties that matter most: - A recomputed value **cannot be stale** — it is produced from the inputs that exist when it is read. - There is **one source of truth**. The state is the fact; the derived value is a view of it, not a second fact that could disagree. - There is **nothing to invalidate**, and invalidation is where most update bugs live. A computation has no cache to get wrong. - The rule lives **next to its use**, so a reader sees how the value is produced without hunting for the code that maintains it. ## What it actually costs The instinct that recomputing is wasteful usually overestimates the work: 1. The computation runs once per evaluation of the unit that contains it — not once per state write anywhere in the app. 2. That evaluation is already doing the framework's own work: building a description of the output, comparing it against the previous one, and touching the host tree. A sum, a comparison or a short filter is small next to that. 3. The figures that decide cost are the **size of the data** and the **number of evaluations**, not the mere presence of a computation. Genuinely expensive derivations exist: sorting or grouping thousands of records, building an index, parsing, layout mathematics. Those are candidates for a cache — after the cost has been observed, not in anticipation of it. ## Derived, cached eagerly, cached lazily | Shape | When the computation runs | Main failure mode | |---|---|---| | Derived during render | every evaluation of the enclosing unit | wasted work when the computation is genuinely heavy | | Cached, recomputed on input change | when an input is seen to change | a wrong dependency set: a stale result, or a cache that never hits | | Cached, recomputed on first read after a change | only when a reader actually asks | work happens at read time, so it can land in an awkward moment | The second and third rows are the same cache with different timing. Both add a comparison of inputs, a retained result and a place for the value to drift from its inputs. That is the trade you are making when you leave the default. ## Reaching past the default When a derivation really is heavy, the options are ordered, and caching is not first: - **Shrink the input.** Deriving from the rows currently displayed instead of the whole collection often removes the cost outright, and leaves no cache behind. - **Derive once, where the inputs live**, so one computation serves every reader instead of each reader repeating it. - **Split the cheap part from the expensive part**, so only the expensive step needs a cache. - **Then cache**, with the dependency set written deliberately, and only where the saving is visible in a measurement rather than assumed. One consequence is worth knowing early: a derivation that builds a fresh collection or object on each evaluation hands a different identity to whatever reads it, even when the contents are equal — and a reader that compares by identity will treat that as a change. The comparison rules themselves are a separate subject; what belongs here is knowing that the derivation is where the new object is born, and that returning a stable result is part of designing one. ## How to answer this in an interview State the default first, then the exception. Deriving during render is correct by construction and the baseline you should have to argue your way out of; caching is an optimisation with its own failure modes, justified by a measured cost, not by the feeling that recomputation is untidy. Saying that in one breath signals that you understand which risk you are trading for which — and it is the answer most interviewers are listening for, because the opposite instinct is what fills real codebases with caches that save nothing and occasionally serve the wrong number.
- If a derivation really is expensive, what would you try before adding a cache?Shrink the input first: derive from the rows actually displayed rather than the whole collection, which often removes the cost outright and leaves nothing to maintain. Then move the derivation to where its inputs live so one computation serves every reader, and split the cheap part from the expensive part so only the expensive step needs a cache.
- Does deriving during render mean the computation runs on every state change in the application?No. It runs when the unit containing it is evaluated — a component function, a template expression, a compiled update block — and that happens when the state that unit reads changes. Unrelated writes elsewhere do not trigger it, which is why the cost is bounded by how often that particular unit re-evaluates.
It is the difference between reading a thermometer when you need the temperature and writing today's temperature on a whiteboard. The whiteboard is faster to read and wrong the moment nobody updates it.
saying these in an interview costs you the question
- Assumes any recomputation is a performance bug without measuring it
- Believes a derived value needs a cache before it can be considered fast
- Thinks a cache is free, ignoring the comparison and the retained result
- Cannot say what goes wrong when a computed value is maintained by hand instead
- Claims deriving during render re-runs on every state change anywhere in the app