Identify information that already exists

A selected category, search text and a list of projects are sufficient to determine the visible projects. Storing the visible list separately creates another value that must stay synchronized with all three inputs. Before adding state, ask whether the value can be calculated from information already available during rendering. Derived values often make both the implementation and its failure modes smaller.

Follow a concrete filter screen

Imagine a portfolio with category buttons and a text field. Keep the category and query in state, then filter the source projects while rendering. The displayed count can come from that filtered array. There is no need for separate effects that update visibleProjects and visibleCount after each input changes, which would temporarily allow the count and list to disagree.

Separate user intent from a calculation

A draft search field may deliberately differ from a submitted search query. Those are two different pieces of user intent, so storing both can be reasonable. A count calculated from the submitted results is different: it is simply a consequence of existing data. Name these responsibilities clearly so a rule against redundant state does not erase meaningful intermediate steps in the interaction.

Optimize expensive derivation only when needed

Filtering a small collection is usually straightforward. If profiling shows that a particular calculation is expensive and reruns unnecessarily, memoization may help cache it under the right dependencies. Memoization should preserve the same result semantics, not become the only reason the component works correctly. Avoid adding a network of caches before understanding the actual cost of the interaction.

Reset state through clear ownership

A detail editor may need a fresh draft when the selected record changes. Decide whether that means a new component identity, an explicit reset action or a controlled parent value. Copying every prop into local state and continuously synchronizing it through an effect can overwrite the visitor’s edits. Model the editing lifecycle, including when unsaved work should be kept or discarded.

Verify coupled values together

Change the category, clear the query, replace the source list and open a different record. Confirm that displayed totals, empty states and highlighted filters all agree in the same render. Look for effects whose only purpose is assigning another derived value. Removing those effects should simplify behavior while preserving the deliberate distinction between saved data, draft input and submitted intent.

Further reading

Put the idea to work.

Explore free browser tools for images, text and developer workflows.

Try a free tool